Przejdź do treści
<code>pen.pl

RYTM — trening pisania

Miniaplikacje

Podgląd

Ładowanie podglądu…

Pomiar tempa i dokładności z zaznaczaniem błędnych znaków na żywo.

0,0 / 5 Brak ocen

Kod źródłowy

Licencja MIT — także do użytku komercyjnego. Zachowaj informacje o autorze i licencji.

HTML
<main><header><h1>Złap rytm.</h1><button type="button" id="next-text">Następny tekst</button></header><div class="typing-room"><section><p class="hint">Przepisz tekst. Pomiar ruszy po pierwszym znaku.</p><p id="reference" aria-label="Tekst do przepisania"></p><label for="typing">Twój tekst</label><textarea id="typing" rows="4" spellcheck="false" autocomplete="off"></textarea><p id="typing-status" class="status" role="status">Gotowy do startu.</p></section><aside><div><strong id="accuracy">—</strong><span>dokładności</span></div><div><strong id="speed">0</strong><span>słów na minutę</span></div><div><strong id="elapsed">0 s</strong><span>od pierwszego znaku</span></div></aside></div><footer>Tempo liczymy jako pięć poprawnych znaków na słowo.</footer></main>
CSS
*{box-sizing:border-box}body{margin:0;font:16px/1.5 Arial,sans-serif}h1,h2,h3,p{margin:0}button,input,textarea,select{font:inherit;border-radius:0}button{cursor:pointer;min-height:44px}input,select{min-height:44px}button:disabled{cursor:default;opacity:.5}button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline:3px solid var(--focus,#1457d9);outline-offset:3px}label{display:block}textarea{resize:vertical;width:100%;max-width:100%}main{min-height:100vh}button:active:not(:disabled){filter:brightness(.9)}[hidden]{display:none!important}.status{min-height:1.5em;font-size:14px}footer{font-size:12px;margin-top:24px}.row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}input,textarea,select{color:inherit}h1{line-height:1.05;letter-spacing:-.04em}button{transition:background-color .15s,color .15s}@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}body{background:#f7f7f4;color:#1f383d;--focus:#9a351e}main{max-width:1050px;margin:auto;padding:38px 5%}header{display:flex;align-items:center;justify-content:space-between;gap:20px}h1{font:64px Georgia,serif;letter-spacing:-3px}button{background:none;border:1px solid #1f383d;padding:8px 16px;color:inherit}.typing-room{display:grid;grid-template-columns:1fr 180px;gap:45px;margin-top:36px}.hint{font-size:14px;color:#4c6469}#reference{font:28px/1.65 Georgia,serif;white-space:pre-wrap;margin:24px 0;padding:18px 0;border-top:1px solid #8a9999;border-bottom:1px solid #8a9999;overflow-wrap:anywhere}#reference .correct{background:#d6e8dc}#reference .wrong{background:#ffdbd0;color:#922713;text-decoration:underline}textarea{padding:14px;border:1px solid #617879;background:white;line-height:1.6}section{min-width:0}section label{font-size:13px;margin-bottom:8px}aside{border-left:1px solid #8a9999;padding-left:28px}aside div{padding:10px 0 26px}aside strong{display:block;font-size:42px;letter-spacing:-2px}aside span{font-size:13px}#typing-status{margin-top:14px}@media(max-width:650px){main{padding:24px 16px}h1{font-size:43px}.typing-room{grid-template-columns:1fr;gap:20px}aside{border-left:0;border-top:1px solid #8a9999;display:flex;justify-content:space-between;padding:12px 0}aside strong{font-size:29px}aside div{padding:0;max-width:95px}#reference{font-size:24px}header{align-items:start}}
JavaScript
function typingStats(input,target,ms){let correct=0;for(let i=0;i<input.length;i++)if(input[i]===target[i])correct++;return {accuracy:input.length?Math.round(correct/input.length*100):0,speed:Math.round(correct/5/Math.max(1000,ms)*60000),complete:input===target};}
$(function(){const texts=['Małe kroki prowadzą do dużych zmian.','Najlepszy pomysł zaczyna się od pytania.','Dobrze napisany kod daje się czytać.'];let index=0,start=null,end=null,timer;function paint(){const text=$('#typing').val(),stats=typingStats(text,texts[index],(end||Date.now())-(start||Date.now()));$('#reference').empty();Array.from(texts[index]).forEach((c,i)=>$('#reference').append($('<span>').text(c).toggleClass('correct',i<text.length&&text[i]===c).toggleClass('wrong',i<text.length&&text[i]!==c)));$('#accuracy').text(text.length?stats.accuracy+'%':'—');$('#speed').text(start?stats.speed:0);$('#elapsed').text(start?Math.floor(((end||Date.now())-start)/1000)+' s':'0 s');}function reset(){clearInterval(timer);start=null;end=null;$('#typing').val('').prop('readonly',false).attr('maxlength',texts[index].length);$('#typing-status').text('Gotowy do startu.');paint();}$('#typing').on('input',function(){if(!start&&this.value.length){start=Date.now();timer=setInterval(paint,500);}if(this.value===texts[index]){end=Date.now();clearInterval(timer);$(this).prop('readonly',true);$('#typing-status').text('Tekst ukończony. Dokładność: 100%.');}else $('#typing-status').text('Przepisano '+this.value.length+' z '+texts[index].length+' znaków.');paint();});$('#next-text').on('click',function(){index=(index+1)%texts.length;reset();$('#typing').trigger('focus');});reset();});
Biblioteki

JavaScript

Edytuj swój pen

Podaj adres e-mail użyty przy zapisie. Wyślemy link do edycji.

Link jest ważny przez 30 minut.