How to prevent multiple decimals in JS calculator?

How to prevent multiple decimals in JS calculator?
0.0 0

#1

I am trying to prevent multiple decimals from being entered into my calculator, but my code isn’t working. How can I fix it?

My html is:

<input type="button" name="dot" value="." id="dot" onclick="calc.output.value += '.'"/>

My jquery is:

var input = '';
$(':button').click(function() {
  input = $(this).attr("value");
 if (input === '.') {
      if (input === '.' + '.') {
        input = '';
      }
    }
});

Thanks!


#2

I don’t know what the rest of your code looks like, but currently when any button is clicked you are assigning its “value” attribute to input. Then you are asking if input is equal to ‘.’. If input is equal to ‘.’ and also equal to ‘..’ then you are resetting input back to a blank string with no dots at all.

Since you always assigning the value of the current clicked button, input will only ever have one character in it, so input will never get set to blank because it is impossible for it to ever be ‘..’ based on your current code logic.


#3

What if I use a Regexp instead?

Something like:

var regexp=/^\[0-9]*\.+$/;

where I’m searching for zero + numbers in front of the decimal, then one or more decimals? (Or do I even need to search for numbers before the decimal?)

How do I make sure the regexp matches at least 2 decimals in a row?


#4

Think about what you want to display based on when a key is pressed.

If I enter the following;

and then enter another dot (.)

.
you want to ignore if the last key pressed was a dot

However, what if I typed:

35.07

and then press dot (.), you want to ignore that last dot also.

Basically, you want to ignore any further dots after the first one is pressed. It will depend on how you are storing the past keys pressed, but let’s say you had a string variable called keysPressed which contains all the buttons pressed before the current button click event.

input = $this.attr("value")
if (!/\./.test(keysPressed)) {
  // no dot pressed before now, so add to keysPressed
  keysPressed += input; // adds input because there was not a previous dot in keysPressed
}

No need to blank anything out, because the above will only allow one dot to ever be in keysPressed.


#5

Perhaps I am not targeting the html appropriately. No matter how I write the function, it doesn’t work. Or am I missing something else?

If I write it like this (majority of code not included):

<form name="calc" id="calc">
<input type="text" name="output" id="output">
<input type="button" name="dot" value="." Id="dot" onclick="dot()"/>
</form>
$(document).ready(function(){
var keysPressed='';
var input='';
$("#dot").click(function(dot) {
input = $this.attr("value")
if (!/\./.test(keysPressed)) {
  // no dot pressed before now, so add to keysPressed
  keysPressed += input; // adds input because there was not a previous dot in keysPressed
}
  });
});

nothing happens when I click on the decimal button.

Alternatively, if I write it like this (majority of code not included):

<form name="calc" id="calc">
<input type="text" name="output" id="output">
<input type="button" name="dot" value="." Id="dot" onclick="calc.out.value += '.'"/>
</form>
$(document).ready(function(){
var keysPressed='';
var input='';
$("#dot").click(function() {
input = $this.attr("value")
if (!/\./.test(keysPressed)) {
  // no dot pressed before now, so add to keysPressed
  keysPressed += input; // adds input because there was not a previous dot in keysPressed
}
  });
});

I can press the decimal as many times as I want.


#6

You have conflicting onclick events. In both scenarios, you have one in your HTML section (i.e. onclick=“dot()” and another in JS code (i.e. $("#dot").click(function() { }). Stick with the one in the JS Code and get rid of the HTML onclick code.


#7

Ok. Got rid of conflicting events and now I get a decimal every time I click that button.

Can I search for multiple decimals being clicked (entered) without storing all click events (keys pressed) in a variable?


#8

If you don’t store the keys pressed somewhere (a variable or an HTML element), then you would have no history to check against.

If you have other questions about your code, make sure to post a link to either your website, github, Codepen, JSFiddle, or other site which has the current code. That way, as you make changes, we can just look at the real-time code without you having copy/paste your updates in your posts.


#9

Here is the link to my calculator: https://codepen.io/velvetstar/pen/xqzeam?editors=1010

At this point, I am not sure how to store all of the buttons clicked into one variable. It seems like it should be written as a function similar to this:

var keysPressed='';
var input='';
input = $this.attr("value")
$(":button").on("click", function(){
keysPressed;
}
});

But since :button targets all of my buttons, that prevents my other JS code, specific to certain buttons, from working. So I have not added it. Perhaps I need to re-write my html?


#10

Your current code shows a keysPressed variable. Why not add the character of the button clicked to the end of this string each time a button is clicked. You can do this in each of your click events. If you can not remember how to add the character to the end, review how to use the += operator or String.prototype.concat.

Then you can create a separate stand-alone function (not related to a specific click event) and use the regular expression logic we discussed earlier in this thread. You could also use an array instead of a string for keysPressed, then you would just push the characters into the array. If you chose to use an array, you would have to use a different method (indexOf or a loop) to look at the arrays values when trying to find a previous decimal.


#11

Ok. So now I have a successful storage variable:

var keysPressed = '';
var input;
$(':button').on('click', function(event) {
  input = $(this).attr("value");
  keysPressed += input;
  console.log(keysPressed);
});

I thought I could write a function that disables the decimal button upon finding a decimal in keysPressed:

function search(){
    var disable=document.getElementById("#dot").disabled = true; 
    if (/\./.test(keysPressed)){
      disable;    
   }
  }
  search();

However, this disables the decimal before one has been found. How do I fix this?


#12

Try

  function search(){
    if (/\./.test(keysPressed)){
      document.getElementById("#dot").disabled = true; 
    }
  }
  search();

#13

Nope. That didn’t work. I can press the decimal as many times as I want.

I also realized the # before “dot” shouldn’t be there and removed it. But that didn’t change anything.


#14

You have:

$(":button").on("click", function(event) {

and

$("#dot").click(function(decimal) {

When a decimal is clicked, both of these are going to execute their anonymous call back functions, so the first one will still allow you to put a decimal. Plus, you never call your search function after a button is clicked. You are calling it one time when the page first loads. It should have been called anytime a button is clicked (the first event handler shown above).

You really only need one event handler (the first one you have above). Then, within the anonymous callback function, you should be doing other tasks depending on the the id of the button clicked. Right now, you have an event handler for all buttons (the first one) and then separate event handlers several of the buttons.

You should rethink your entire logic and have the majority of the special conditions checked within that one main event handler callback function.

You are trying to band-aid your existing solution by patching sections, but you should step back and look at the bigger picture. What I mean by all of this, is that you need to write out your algorithm first before trying to write JavaScript code. Only once you have your logic written out, should you begin trying to write any code.


#15

I have moved the individual button functions so that they are all under a main button click function.

I need to re-write my code pertaining to the decimal button so that not only can someone only press one decimal at a time, but can press the decimal again for a different number in the same equation. For example: 3.2 + 3.2. Right now, I have it written so that once you push the decimal, it is disabled. So only one number could have a decimal until you refresh the page.

My pseudo code would be:

If button clicked is decimal {
If decimal clicked, only allow one decimal unless an operand button ( +, -, x, /) is clicked afterwards.
If an operand is clicked and then another number, the decimal button may be clicked again, once only.
}
When the = button is clicked, reset keysPressed to " ".

How do I translate that into actual JS? Or is that oversimplified?