mirror of https://github.com/shadowfacts/type.git
WPM tracking
This commit is contained in:
parent
3d780753c4
commit
59999d084f
13
css/main.css
13
css/main.css
|
@ -33,10 +33,23 @@
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#toolbar > #info {
|
||||||
|
float: right;
|
||||||
|
margin-right: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar > #info > #paused {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
margin-top: 33px;
|
margin-top: 33px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#content.paused > .CodeMirror {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
/* Index */
|
/* Index */
|
||||||
.prev-list {
|
.prev-list {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
|
69
js/type.js
69
js/type.js
|
@ -4,6 +4,9 @@ var incompleteMark;
|
||||||
var focused = false;
|
var focused = false;
|
||||||
let invalids = [];
|
let invalids = [];
|
||||||
var fileLines;
|
var fileLines;
|
||||||
|
// WPM tracking
|
||||||
|
var lastStartTime;
|
||||||
|
var elapsedTime;
|
||||||
|
|
||||||
let hash = window.location.hash.substring(1);
|
let hash = window.location.hash.substring(1);
|
||||||
let hashBits = hash.split("/");
|
let hashBits = hash.split("/");
|
||||||
|
@ -114,7 +117,7 @@ function setup(data, mime) {
|
||||||
className: "incomplete"
|
className: "incomplete"
|
||||||
});
|
});
|
||||||
|
|
||||||
focused = true;
|
resume();
|
||||||
|
|
||||||
editor.on("focus", handleFocus);
|
editor.on("focus", handleFocus);
|
||||||
editor.on("blur", handleBlur);
|
editor.on("blur", handleBlur);
|
||||||
|
@ -130,11 +133,11 @@ function setup(data, mime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFocus() {
|
function handleFocus() {
|
||||||
focused = true;
|
resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleBlur() {
|
function handleBlur() {
|
||||||
focused = false;
|
pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMouseDown(instance, event) {
|
function handleMouseDown(instance, event) {
|
||||||
|
@ -168,6 +171,14 @@ function handleKeyDown(event) {
|
||||||
} else if (event.keyCode == 9) { // tab
|
} else if (event.keyCode == 9) { // tab
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
handleTab(event);
|
handleTab(event);
|
||||||
|
} else if (event.keyCode == 27) { // escape
|
||||||
|
event.preventDefault();
|
||||||
|
pause();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (event.keyCode == 27) {
|
||||||
|
event.preventDefault();
|
||||||
|
resume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,6 +232,7 @@ function handleEnter(event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateIncompleteMark();
|
updateIncompleteMark();
|
||||||
|
updateWPM();
|
||||||
save();
|
save();
|
||||||
} else {
|
} else {
|
||||||
goToNextChunk();
|
goToNextChunk();
|
||||||
|
@ -437,6 +449,7 @@ function load() {
|
||||||
let chunk = val[filePath].chunks[val[filePath].chunk];
|
let chunk = val[filePath].chunks[val[filePath].chunk];
|
||||||
loadInvalids(chunk);
|
loadInvalids(chunk);
|
||||||
loadCursor(chunk);
|
loadCursor(chunk);
|
||||||
|
loadElapsedTime(chunk);
|
||||||
} else {
|
} else {
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
@ -458,6 +471,7 @@ function save() {
|
||||||
let chunk = file.chunks[file.chunk];
|
let chunk = file.chunks[file.chunk];
|
||||||
saveInvalids(chunk);
|
saveInvalids(chunk);
|
||||||
saveCursor(chunk);
|
saveCursor(chunk);
|
||||||
|
saveElapsedTime(chunk);
|
||||||
|
|
||||||
localforage.setItem(repo, val)
|
localforage.setItem(repo, val)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
|
@ -515,6 +529,14 @@ function saveCursor(obj) {
|
||||||
obj.cursor = editor.getCursor();
|
obj.cursor = editor.getCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadElapsedTime(obj) {
|
||||||
|
elapsedTime = obj.elapsedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveElapsedTime(obj) {
|
||||||
|
obj.elapsedTime = elapsedTime;
|
||||||
|
}
|
||||||
|
|
||||||
function setTheme(theme) {
|
function setTheme(theme) {
|
||||||
if (theme != "default") {
|
if (theme != "default") {
|
||||||
$("head").append(`<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.19.0/theme/${theme}.min.css">`);
|
$("head").append(`<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.19.0/theme/${theme}.min.css">`);
|
||||||
|
@ -532,6 +554,47 @@ function setCursor(pos) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateWPM() {
|
||||||
|
if (focused) {
|
||||||
|
// update elapsed time
|
||||||
|
if (!elapsedTime || isNaN(elapsedTime)) {
|
||||||
|
elapsedTime = Date.now() - lastStartTime;
|
||||||
|
} else {
|
||||||
|
elapsedTime += Date.now() - lastStartTime;
|
||||||
|
}
|
||||||
|
lastStartTime = Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate words typed
|
||||||
|
let typed = editor.doc.getRange({ line: 0, ch: 0 }, editor.getCursor());
|
||||||
|
let words = typed.split(/[\s,\.]+/).length;
|
||||||
|
|
||||||
|
let seconds = elapsedTime / 1000;
|
||||||
|
if (seconds >= 60) {
|
||||||
|
// update real WPM
|
||||||
|
let minutes = seconds / 60;
|
||||||
|
$("#wpm").text(Math.round(words / minutes));
|
||||||
|
} else {
|
||||||
|
// extrapolate forwards
|
||||||
|
let scaledWords = words / (seconds / 60);
|
||||||
|
$("#wpm").text(Math.round(scaledWords));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pause() {
|
||||||
|
focused = false;
|
||||||
|
elapsedTime += Date.now() - lastStartTime;
|
||||||
|
$("#paused").text("Paused");
|
||||||
|
$("#content").addClass("paused");
|
||||||
|
}
|
||||||
|
|
||||||
|
function resume() {
|
||||||
|
focused = true;
|
||||||
|
lastStartTime = Date.now();
|
||||||
|
$("#paused").text("");
|
||||||
|
$("#content").removeClass("paused");
|
||||||
|
}
|
||||||
|
|
||||||
String.prototype.hasOnlyWhiteSpaceBeforeIndex = function(index) {
|
String.prototype.hasOnlyWhiteSpaceBeforeIndex = function(index) {
|
||||||
return this.substring(index) == this.trim();
|
return this.substring(index) == this.trim();
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,6 +70,10 @@
|
||||||
<option value="yeti">Yeti</option>
|
<option value="yeti">Yeti</option>
|
||||||
<option value="zenburn">Zenburn</option>
|
<option value="zenburn">Zenburn</option>
|
||||||
</select>
|
</select>
|
||||||
|
<div id="info">
|
||||||
|
WPM: <span id="wpm">Unknown</span>
|
||||||
|
<span id="paused"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
|
|
Loading…
Reference in New Issue