How to do something when backspace or delete is pressed - javascript

So I am having trouble getting my code to do something when I hit backspace or delete.
The code I have works just fine. It runs the following code, updating the size and value of multiple text input fields.
It calls compute(), which calls update() multiple times through updateAllFields().
function compute(input,number){
var decider = String(input.value);
updateAllFields(decider,number);
}
function update(label,convert,decider,number){
var updater = document.getElementById(label);
updater.value = parseInt(decider, number).toString(convert);
updater.style.width = ((updater.value.length + 1) * 12.5) + 'px';
}
function updateAllFields(decider,number){
update('binary',2,decider,number);
update('octal',8,decider,number);
update('decimal',10,decider,number);
update('hexadecimal',16,decider,number);
}
Now, that all runs just fine. I ran into an issue that, when an entire field is deleted, I get NaN, and can no longer edit the text fields unless I outsmart the NaN value.
How it happens is that that if a user hits "Ctrl+home", then backspace (wiping the entire field), NaN appears.
What I want, instead, is that when NaN would have appeared, all of the text inputs are reset to the same size and appearance that they were when their placeholders were showing.
I had looked this up, and found the following:
var input = document.getElementById('display');
input.onkeydown = function() {
var key = event.keyCode || event.charCode;
if( key !== 8 && key !== 46 )
return true;
};
It doesn't work. I even tried replacing the return false to instead read my replacement code:
function refresh(label,number){
var refresher = document.getElementById(label);
refresher.value = '';
refresher.size = number;
}
function refreshAllFields(){
refresh('binary','3');
refresh('octal','2');
refresh('decimal','4');
refresh('hexadecimal','8');
}
And that doesn't work.
What am I doing wrong? How can I get my fields to just reset to their original states if the entire text-field of one is wiped out?

You don't need to decrease the possibility of error. You need to prevent errors at all. Just validate the input data and you won't get NaN.
Simply add a check in your compute if the input is an integer:
function compute(input,number){
var decider = String(input.value);
if (isNumeric(decider))
{
// do something else
decider = "0"; // for example
}
updateAllFields(decider, number);
}
where isNumeric is a function which determines if a string represents number. There are many ways to do this, for example this:
function isNumeric(value)
{
if (isNaN(value)) {
return false;
}
var x = parseFloat(value);
return (x | 0) === x;
}
Also, you can stop passing your decider and number to every function as a string:
function compute(input, number){
if (isNumeric(input.value))
{
updateAllFields(parseInt(input.value, number)); // val is a Number now
} else {
updateAllFields(0); // for example
}
}
function update(label,convert,val){
var updater = document.getElementById(label);
updater.value = val.toString(convert);
updater.style.width = ((updater.value.length + 1) * 12.5) + 'px';
}
function updateAllFields(val) {
update('binary',2,val);
update('octal',8,val);
update('decimal',10,val);
update('hexadecimal',16,val);
}

Related

Should I use an array instead of a random number generator here?

I am making a memory game using Javascript, HTML, and CSS.
Here is a brief description of the game:
The program generates a random number, which is shown on
screen.
After about 5 seconds, the number disappears and a pop-up box appears on the screen, asking for the user to enter the number he or she just saw.
If the number matches the one that was previously on screen, then an alert box with the word "Correct" appears. If not, an alert box with the text "Nope. Nice try" appears.
Here's my problem:
The alert box says "Nope. Nice try" even when I enter the correct number.
Here is what I've coded thus far:
(Keep in mind that I have yet to any implement setInterval/setTimeout functions. I made the "hide" function manual for convenience.)
JS:
/* game level = easy
numbers from 1-9000 are generated */
function random(a){
a = Math.floor(Math.random() * (9000 - 1) + 1);
document.getElementById("screen").innerText = a;
}
function getInput(a){
var input = window.prompt("Enter the number you just saw:");
if(input === a){
alert("Correct!");
}
else{
alert("Nope. Nice try.");
}
}
/* hide toggle */
function hide() {
var x = document.getElementById("screen");
if (x.style.display === "none") {
x.style.display = "none";
} else {
x.style.display = "none";
}
}
My question: Would it be ideal to use an array of numbers from 1-9000 instead?
With an array, I figure I can do something like this:
for(var i = 0; i < arr.length; i++){
if(//){
}
else{
}
}
Thank you for reading.
From what I can tell, you are treating a as a variable with a scope larger than it actually has. a is an argument, and its scope doesn't reach beyond the function it is declared in.
In this case, a in random(a) and a in getInput(a) are two unrelated entities with a scope that doesn't overlap.
A solution could be to make a a global variable and declare it outside of any function, like
var a;
function random(){
a = Math.floor(Math.random() * (9000 - 1) + 1);
document.getElementById("screen").innerText = a;
}
function getInput(){
var input = window.prompt("Enter the number you just saw:");
if(input == a){ // make '===' into '==' instead btw
alert("Correct!");
}
else{
alert("Nope. Nice try.");
}
}
I see that you receive a String from the user, but you try to compare it to an integer. So lets say that a = 1, and input ='1' , which means they will never be equal.
You should onvert the string to an int and after that do the comparison.
Try
input == a
Instead of
input === a
Math.random returns a number and you're comparing it against a string with type match.
console.log(1 === '1');
console.log(1 == '1');

jQuery getting sum with keypress always one step behind

I am trying to create an calculator in which I want add/sum on every key press I make like this:
$('#padd').keypress(function() {
var ypoints = "200";
var points = parseInt( $(this).val() );
console.log( "Points: " + (points + parseInt(ypoints)) );
});
My issue is that it seems like "points" always is one step behind. Lets say that my "ypoints" is 200 and I type in first 1, the console.log says "NaN"? If I then type in a "10" the console.log says "201" while in fact it should say "210"?!? If I then add an "100" in the add field it says "210" but it should say "300". Always one keypress behind?!?
What am I missing here or is this not the correct way to do this?
Any help is appreciated and thanks in advance :-)
Try using the keyup function instead (although you might not want to listen for key* events at all, see below):
$('#padd').keyup(function(){
var ypoints = 200;
var points = parseInt($(this).val());
console.log("Points: "+(points+ypoints));
});
Instead of keyup, you should listen for the explicit input event:
$('#padd').on("input", function(){
var ypoints = 200;
var points = parseInt($(this).val());
console.log("Points: "+(points+ypoints));
});
An example when listening for the input event trumps using keyup is when using an input of type number. In a (not so) modern browser, this adds a stepper to the input field, which you can use to increment or decrement the inputs value by 1 using your mouse. This does not fire the keyup event (no keys are pressed) but nevertheless changes the value.
It is really a matter of when certain events are fired and the state of the input's value at that time. There is an explanation on quirksmode.org:
keyup
Fires when the user releases a key, after the default action of that key has been performed.
and more information on the input event on MDN:
The DOM input event is fired synchronously when the value of an or element is changed.
Try this, its a working code : Fiddle
$('#padd').keyup(function(){
var ypoints = "200";
var points = parseInt($(this).val());
alert("Points: "+(points+parseInt(ypoints)));
});
You can also code this way...
function GetTextboxAmount(obj) {
var retVal = 0;
try {
if (obj.val() == "") {
retVal = 0;
} else if (obj.val() == '') {
retVal = 0;
} else if (isNaN(parseFloat(obj.val()))) {
retVal = 0;
} else {
retVal = Math.round(parseFloat(obj.val()));
}
} catch (e) { retVal = 0; }
obj.val(retVal);
return retVal;
}
$('#padd').keyup(function(){
var ypoints = "200";
var points = GetTextboxAmount($(this));
console.log("Points: "+(points+parseInt(ypoints)));
});
Problem in ParseInt function.
try this Code:
$('#padd').keypress(function(){
var ypoints = "200";
var points = parseInt($(this).val());
console.log("Points: "+parseInt(ypoints+points));
});

JavaScript using isNaN to validate returns NaN

I have some code here that will make validations of whether or not the input from a text box is NOT an empty string and isNaN. When i do these validations on amounts entered, i would like it to add them up.. however when a user does not enter anything in one or more amount fields the program should just add entered fields. But instead i get NaN showing in the total field.
link to full code: http://jsfiddle.net/KxNqQ/
var $ = function (id) {
return document.getElementById(id);
}
var calculateBills = function () {
var myErrorFlag = "N";
for (i = 1; i <= 4; i++) {
AmountNumber = 'amount' + i;
AmountValue = $(AmountNumber).value;
if (AmountValue != "" && isNaN(AmountValue)) {
$(AmountNumber).style.color = "red";
myErrorFlag = "Y";
} else {
$(AmountNumber).style.color = "black";
myErrorFlag = "N";
}
}
if (myErrorFlag != "Y") {
var Amount = 0;
for (i = 1; i <= 4; i++) {
Amount += parseInt($('amount' + i).value,10);
}
$('total').value = Amount;
}
}
var clearFields = function () {
for (i = 1; i <= 4; i++) {
itemName = 'item' + i;
$(itemName).value = "";
}
for (i = 1; i <= 4; i++) {
amountName = 'amount' + i;
$(amountName).value = "";
}
$('total').value = "";
}
window.onload = function () {
$("clearfields").onclick = clearFields;
$("addbills").onclick = calculateBills;
}
I think you've got your requirements a little bit confused, or at the very least I was confused by them. So in order to answer your question, I'm going to rephrase the requirements so I understand them better. This is a useful exercise that I try to do when I'm not 100% sure of the requirements; if I can't get the requirements right, what's to say I'll get the code right?
So the requirements – as I understand them – are:
Given each amount input
When the input has a value
And that value is a number
Then add the value to the total
And make the input color black
But if the input does not have a value
Or that value is not a number
Then make the input color red
Going through your code, I can see a number of problems with it. First, I noticed that both AmountNumber and AmountValue are global variables, because they were not declared local with the var keyword. So before fixing our code, let's change that. Let's also change the variable names to something that more accurately describe what they are, hopefully making the code easier to understand:
var input = $('amount' + i);
var value = input.value;
Now, note that I chose to store the element in the input variable. This is so we don't have to look it up multiple times within the loop. Looking things up in the DOM can be expensive so we'll want to keep it to a minimum. There are other was to look up elements as well, such as getElementsByClassName, querySelector and querySelectorAll; those are left as an exercise for the reader to research and evaluate.
Next, in each iteration of the loop, you check that AmountValue is not a string and simultaneously is not a number:
if (AmountValue != "" && isNaN(AmountValue)) {
This will be true so long as AmountValue is truthy (which is the case for non-empty strings) and so long as isNaN thinks it's a number (which is the case for strings that contain numbers.) It really is rather confusing; if I understand your code correctly this clause is there to check for invalid input and if it is true should mark the input field red and set a flag. I.e. this is the but clause in the aforementioned requirements.
Let's rewrite this to be the when clause instead, we'll take care of the but later. Before we do that, let's look at the myErrorFlag. It's used – I think – to see whether all input is well formed and in that case, add it all up. Well, validation and summation can be done in one fell swoop, so let's get rid of the flag and sum the values while validating them. So we replace myErrorFlag with a total variable:
var total = 0;
Now, let's get back to our clause. The requirements say:
When the input has a value
And that value is a number
Then add the value to the total
In code, that should look something like this:
if (value && !isNaN(value)) {
total += parseInt(value, 10);
input.style.color = 'black';
}
There are a couple of things going on here. For one, the if statement has been turned on its head a bit from what it was. It first checks to see that value is truthy, then that it is a number. The second check can be a bit tricky to read, because it is essentially a double negation; in english it reads "is not not a number", i.e. "is a number". I'll leave it as an exercise for the reader to figure out whether there's a more easily understood way of writing this check.
Now what about the but clause in our requirements?
But if the input does not have a value
Or that value is not a number
Then make the input color red
Well, it's essentially the inverse of our previous statement, so let's simply add an else clause:
else {
input.style.color = 'red';
}
Because the requirements doesn't mention the total variable in this clause, it is simply ignored and doesn't show up in the end result.
Adding it all up (no pun intended) the code – with comments – looks like this:
var calculateBills = function () {
var total = 0;
for (i = 1; i <= 4; i++) {
// Given each amount input
var input = $('amount' + i);
var value = input.value;
if (value && !isNaN(value)) {
// When the input has a value
// And that value is a number
// Then add the value to the total
total += parseInt(value, 10);
// And make the input color black
input.style.color = 'black';
} else {
// But if the input does not have a value
// Or that value is not a number
// Then make the input color red
input.style.color = 'red';
}
}
$('total').value = total;
};
There are more things that could be learned from this to make for better code. For instance, this code will break if the number of inputs change, or if their id names change. This is because they are selected specifically by their IDs and as such, if those change then this code will no longer function.
Another potential issue is that we're setting inline styles on the inputs as we loop over them. This means that in order to keep this code up to date with the styling of the site, it'll have to change. Generally, mixing styling and functionality like this is not a good idea and should be avoided. One way of doing so is to use class names instead, and toggle these on and off. Incidentally, this could also help the previous problem I mentioned.
There are other problems as well, but we'll leave those for another day. Hope this helps!
Try this
var calculateBills = function () {
var Amount = 0;
for (i = 1; i <= 4; i++) {
var AmountElement = $('amount' + i),
AmountValue = AmountElement.value;
if (AmountValue != "" && !isNaN(AmountValue)) {
AmountElement.style.color = "red";
Amount += parseInt(AmountValue,10);
} else {
AmountElement.style.color = "";
}
}
$('total').value = Amount;
};
Demo
Anyway, instead of using elements with id like id="amount1", id="amount2", id="amount3", etc., you could use classes (e.g class="amount") and get them with .getElementsByClassName

keep add the value without overwrite the function

function checkData() {
var temp = 0;
var totalMarks = countMark(temp);
if (totalMarks != 100)
window.alert("Marks must total 100");
}
function countMark(mark) {
var totalMark = 0;
totalMark += parseInt(mark)
return totalMark;
}
function doAdd() {
var taskid = document.getElementById("taskid").value;
var taskname = document.getElementById("taskname").value;
var taskmark = document.getElementById("taskmark").value;
if (taskid.length === 0)
window.alert("Task Id cannot be empty!");
if (taskname.length === 0)
window.alert("Task name cannot be empty!");
if (taskmark.length === 0)
window.alert("Task Mark cannot be empty!");
else if (!markpattern.test(taskmark))
window.alert("Invalid data in mark field");
var marks = parseInt(document.getElementById("taskmark"));
if (marks < 0 || marks > 100)
window.alert("Marks out of range. Please re-enter");
countMark(marks);
}
My question is when i keep call the doAdd() function. my marks will keep adding . want to do like passing reference like in C++ . my function countMark(...) will keep adding .
after that, when my form submitted, my form will call the function checkData()
If my totalmark is not 100 . will prompt out the alert and error.
but my code is not working . I guess that my countMark function wrong somewhere
If I understand you correctly, you're looking for the equivalent of a static variable - something that gets initialized the first time the function is called, and keeps it's value for subsequent calls.
Take a look at this related question: https://stackoverflow.com/a/1535650/2444111
The top answer (by CMS) is talking about class-based static variables, which are not quite the same thing.
The second answer (by Pascal MARTIN) is what you're looking for. It takes advantage of the fact that JS functions are also objects, and stores the variable as a property of the function object. This is a better solution than using a global variable (or a property of window, which is what a global actually is)
There are several issues in your code and it's really hard to say what your intention was. But I will address what I found.
In the following piece of code you are requesting a DOM Element and try to parse it as an Integer. The result of that type convertion is always NaN. Maybe wanted to get the value attribute of your element, like you did before. (Also, don't request the same element multiple times. Request it once, save the result in a variable and use that variable from that on).
var marks = parseInt(document.getElementById("taskmark"));
if (marks < 0 || marks > 100)
window.alert("Marks out of range. Please re-enter");
countMark(marks);
Your function countMark is pretty useless, because it will always return whatever Number you pass to it (see comments in your code).
function countMark(mark) {
var totalMark = 0; //create a new variable with value 0
totalMark += parseInt(mark) //add "mark" to that variable
return totalMark; //return that variable => 0 + mark = mark (and if mark = NaN => 0 + mark = NaN)
}
Maybe you wanted to make totalMark a global variable, than you would need to define it outside of your function:
var totalMark = 0;
function countMark(mark) {
totalMark += parseInt(mark);
return totalMark;
}
Last but not least, lets analyse your function checkData:
function checkData() {
var temp = 0; //create a local variable with value 0
var totalMarks = countMark(temp); //pass 0 to countMark => return 0 => totalMarks = 0
if (totalMarks != 100) //always true since totalMarks is always 0
window.alert("Marks must total 100"); //will always alert
}

Autocorrection acts weird on duplicated fields

I have a form that users can duplicate, so they can submit multiple forms in one times. This works fine. However, i noticed that users don't use it the right way. For example, i ask for initials and people fill out their front name. PHP checks all fields and auto-corrects them if necessary, but this turns John into J.O.H.N.
Anyway a good way would be to autocorrectfields. This works on the initial form, but goes wrong on the duplicated forms. Especially initials acts weird. My knowledge of jQuery and Javascript is very limited, so after puzzling for weeks i still don't know how to solve it. Suggestions are welcome.
Fiddle: http://jsfiddle.net/QUxyy/15/
JS
// Lowercase
$(".lowercase").keyup(function(e)
{
$(".lowercase").val(($(".lowercase").val()).toLowerCase());
if (/[a-z]/g.test(this.value))
{
this.value = this.value.replace(/[^a-z ]/g, '');
}
});
// Initials
$(".initials").focus(function() {
var current = $(".initials").val();
$(".initials").keyup(function(e) {
var key = String.fromCharCode(e.keyCode);
if (key >= 'A' && key <= 'Z') {
current += key + ".";
this.value = current;
}
else {
current = "";
}
});
$(".initials").blur(function() {
var i = $(".initials").val();
var last = i[i.length - 1];
if (last != "." && i.length !== 0){
this.value += ".";
}
});
});
// Capitalize
$(".cap").keyup(function(e)
{
function convertToUpper() {
return arguments[0].toUpperCase();
}
val = this.value.toLowerCase().replace(/\b[a-z]/g, convertToUpper);
this.value = val;
});
Click for full code and preview
In your callback event handlers function for .voorletters use 'this', e.g:
SEE DEMO
$(document).on("keydown", ".voorletters", function(e) {
var i = $(this).val();
if (e.keyCode == 8 && i.charAt(i.length - 1) == ".") {
$(this).val(i.slice(0, -1));
current = $(this).val();
}
})
And you should do it for all your call back function as .initials, .lowercase, etc...

Categories

Resources