Building A Timer in Javascript/jQuery - javascript

I'm currently working on a website which would work somewhat like this one:
http://www.keyhero.com/free-typing-test/
I'd like to build a timer which starts on the user's first key press, and ends when the user presses 'Enter'. When the timer ends, I'd want to get the resulting time and push it off to the backend (Django for me) where the WPM will be calculated. However, I have no idea how to get started on this, as I have little experience with jQuery and Javascript and haven't been able to find useful pages.
So my question is, how would I do this? I can post some of my Django files if a better picture of what I am asking is needed.

You manage the key events with .keypress() for know when the person click in the keyboard.
http://api.jquery.com/keypress/
And for key = "ENTER", you just need to validate if is equal to key 13
$('#id_tag').keypress(function (e) {
var key = e.which;
if(key == 13) // the enter key code
{
alert("Clicked on enter");
return false;
}
});
I see that post too, that are using keyup():
JQuery Event for user pressing enter in a textbox?

Well you're going to have to capture the keypress/keydown/keyup event in a jQuery event, then start a setInterval and have that function increment a counter variable of sorts. Then you just reference that variable whenever you want to see how many seconds have passed. A crude example would be:
window.secondsSinceTyped = 0;
$('#textbox').one('keypress', function (e) {
window.setInterval(function () {
window.secondsSinceTyped++;
}, 1000);
});
Then just reference the variable secondsSinceTyped whenever you want to check the time. Note that I used the jquery one binding which will only bind the event once so that every time you type it doesn't rebind the event.

Related

Handling multiple keys pressed at once in JavaScript

For context: this is a JavaScript app running in the Xbox One. All of this is happening through the Xbox's virtual keyboard. Keep in mind that since I have figured out how the events are being fired, this shouldn't matter anymore, just how to deal with the two events at once.
It's not really multiple keys, what is happening is when I turn on CAPS for my app, I am getting two events keys at once: shift and whatever key I am actually pressing. The problem this is causing is that shift seems to be overriding whatever I am trying to spell, and no key is displayed in my input boxes.
I currently have a global function which takes care of all special events in the app, and I would like to handle this issue from over there but am not sure how to go about this issue.
Here is what I currently have:
// this is the global function where I would like to solve the issue
onStartup(function () {
var $html = $('html')
$html.on('keydown', function (evt) {
if (evt.isDefaultPrevented()) return
console.warn('key being pressed:', evt.keyCode)
if (evt.keyCode === 16) { // Note: 16 is shift's keycode
// do something to prevent shift from overriding the actual key I want to press.
return
}
})
})
When I press a key without CAPS being turned on, say a, which has the keyCode of 65, we have the following output:
key being pressed: 65
If however I try to do a capital a (or A), this is what happens:
key being pressed: 16
key being pressed: 65
What can I do to stop the shift from preventing me from actually typing the capital keys?
I figured it out! All I had to do was when shift was fired, to call evt.stopImmediatePropagation().
So basically, for my code:
// ...
if (keycodeControls.is('shift', evt)) {
evt.stopImmediatePropagation()
}

Twitter Typeahead differentiate between events

I'm designing a system that allows users to annotate elements with either strings or terms from a vocabulary. I use Twitter typeahead for autocompletion and want to distinguish between an entered string and a term.
I am not able to figure out how to differentiate between the following situations:
a user pressing enter after coming up with its own value
a user pressing a down (or up) arrow (thereby selecting an autocompletion option) and pressing enter
The event listeners I wrote:
$("#itemInp").on('typeahead:select', function(event, term) {
console.log("save: term", term);
});
$("#itemInp").on('keyup', function(event) {
if(event.which == 13) {
var string = $("#itemInp").val();
console.log("save: string", string);
}
});
With the following HTML:
<input id="itemInp"><input>
The first listener catches all selected typeahead terms, allowing for proper saving of the term. Problem is, the second listener is also triggered in case a user presses down and enter, selecting a typeahead term, which is now also saved as a plain string. Is there a way to not trigger the second listener in case a typeahead suggestion is selected?
A fiddle with the code loaded:
https://jsfiddle.net/zban3vs6/1/
Edit:
I considered a number of hacks, but all come with their own problems:
Add a special character to the string shown in input at the moment it is selected, by adding custom Typeahead display: https://jsfiddle.net/2t9rzhwf/
This causes an additional character to be introduced, which is troublesome if a user presses the down arrow without pressing enter.
Attempt at sequencing the listeners, have the term listener trigger first, set a boolean to true, and filter on this boolean in the second listener. Don't like this way of filtering, since it introduces a delay.
The solution provided by #peter-clause, checking if the selected value is in the list of available items. But that way I can not keep track of whether the user intended to use the autocomplete option to select a term or explicitly is adding a plain string.
I had a similar problem. This is how I solved it.
var wasSelected = false;
$("#itemInp").on('typeahead:select', function(event, term) {
wasSelected = true;
console.log("save: term", term);
});
$("#itemInp").on('change', function(event) {
if(!wasSelected) {
var string = $("#itemInp").val();
console.log("save: string", string);
}
wasSelected = false;
});
A rather hacky solution, but you could check if the selected value is in the list of available items.
if (states.indexOf(string) == -1) {
//...
}
See https://jsfiddle.net/zban3vs6/2/

filtering data using .keypress - no plugins

I am trying to filter data using .keypress. My current approach is to capture the data from .keypress and pass to my filter function. I am successful in returning data that begins with a letter. So if I type A into my field it will return all cats that begin with A. I would like to narrow my search by typing in more letters and have it update each time. Is there a simple solution here? Here is the code
// retrieve data from key press
$("input").keypress(function (e) {
if (e.which !== 0 && e.charCode !== 0) {
var criteria = String.fromCharCode(e.keyCode|e.charCode);
}
$.getJSON('cats.json', function(cats) {
filterCats(cats, criteria);
});
});
// filter function
function filterCats(cats, criteria){
$.getJSON('cats.json', function(cats) {
//var filteredData = cats.filter(function(c){return c.breed.toUpperCase().indexOf(criteria.toUpperCase()) !== -1;});
var filteredData = cats.filter(function(c){return c.breed.toUpperCase().indexOf(criteria.toUpperCase()) === 0 ;});
renderData(filteredData);
});
}
As others mentioned, keyup is better because it fires after the key is released.
keydown
Fires when the user depresses a key. It repeats while the user keeps the key depressed.
keypress
Fires when an actual character is being inserted in, for instance, a text input. It repeats while the user keeps the key depressed.
keyup
Fires when the user releases a key, after the default action of that key has been performed.
Above from http://www.quirksmode.org/dom/events/keys.html
Also as the other answer states, running your code immediately after every key press could result in a lot of requests sent to the server.
Instead, try throttling it with a timeout.
var timeout, criteria;
$('input').keyup(function(e) {
clearTimeout(timeout);
timeout = setTimeout(function() {
criteria = this.value;
$.getJSON('cats.json', function(cats) {
filterCats(cats, criteria);
});
}.bind(this), 125);
});
As Andy pointed out in a comment, you need to use the value of the input, since you are currently looking at a single character upon each character entry. As Hossein Shahsahebi pointed out, keyup would be a more accurate event for what you desire to do. Also, do not forget about pasting, which should trigger the same logic.
I would like to add that I believe it is undesirable to do the searching upon each character entry. Imagine someone typing really quickly. You will have a lot of requests sent to the server. I would rather wait for a while before doing the search. When the event is triggered, store the current time in a variable and use setTimeout to wait for a second or so before calling the filterCats function. Whenever the event runs, override that variable to the current moment. When filterCats is executed, check whether the variable's value is old-enough. If not, return without filtering. If so, do the filtering. This will decrease server load due to this feature drastically.

jQuery: avoid checking if the key pressed is 'enter' everytime

In the code below, instead of using on keydown, is there a way I can use on e.which === 13 where the keydown is? This was it wont have to check each time a key is pressed, and will work only when enter is pressed.
Current Code
$('.search').on('keydown', function(e) {
if(e.which === 13) {
// enter key pressed
var value = this.value; // this is the inputs value
console.log(value);
}
});
What I hope to do (pseudo code)
$('.search').(when key === 13 is pressed) { // Only if the enter key pressed
// enter key pressed
var value = this.value; // this is the inputs value
console.log(value);
}
});
Can something like this be done?
You could use a higher-order function to extract that logic for you:
function onlyOnEnter(fn) {
return function(e) {
if(e.which === 13) {
fn.apply(this, arguments);
}
}
}
Usage:
$('.search').on('keydown', onlyOnEnter(function(e) {
var value = this.value; // this is the inputs value
console.log(value);
})
);
That way, your callback function will only be called when the key pressed is an enter.
Not really.
The best you can do is capturing events (you are using on but it could be any other event capturing method). There are many different kind of events (mouse events, keyboard events, control specific events, etc.), you have to look at the event, since each event type will have different properties.
For key pressing, there are some events available for capturing such as keypress, keydown and keyup. You can't expect that one specific key will have an event on its own because you want so save one line of code.
No, this isn't really possible (at least not for the purposes of your code) nor does it make a lot of sense. The keydown event is fired whenever a key is pressed.
Whether you are manually checking to see if it's the enter key or whether the browser or jQuery is doing it internally isn't tremendously relevant - regardless the browser will need to check which key was pressed any time any key is pressed to test whether it was the enter key.
Essentially you're wasting your time. There isn't going to be any measurable performance optimization by trying to do this. No matter how you try to detect the enter key being pressed, it will be tested for every keydown or keypress event regardless of which key is pressed.

Determining if key is pressed down in Javascript

I'm writing a platform game for my university project using the canvas element and Javascript. I'm well on my way, but I'm stuck at how to see if a certain key is being pressed in my players update loop.
I was thinking like this:
if(d) {
// move player right
} else if(a) {
// move player left
} else if(w) {
// move player up
} else if(s) {
// move player down
}
That's psudocode, obviously. The only resources to key presses in Javascript that I can find are events, nothing to see if a key is being pressed at a certain point.
Can anyone shed some light on this?
Setup 4 boolean variables if key is up or down. On keydown set it to true, on keyup set it to false. Than you can do if(key_d == true) { // key d is pressed }
That's the best way to do it. Its not "hacky", add event listeners to handle key presses.
I don't think you can get around using keydown, keyup, or keypress for determining which keys are pressed. However, instead of running this code within one of those event handlers, you could set and unset some global flag within them. Then, when this code runs (I'm assuming it'll be on some kind of interval?), it could check for the flag.
You need an event listener.
//function foo, returns keypress
function foo(e){
var evt=(e)?e:(window.event)?window.event:null;
if(evt){
var key=(evt.charCode)?evt.charCode:
((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
return key;
}
//set event listener
//you could also attach this to your canvas, but that will require tricks
//to make the canvas focusable
document.addEventListener('keydown', foo);

Categories

Resources