jQuery getting sum with keypress always one step behind - javascript

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));
});

Related

JQuery - adding value to input, but one input has no ".value" property

So I want to have a function, that writes to an input like a real human (by triggering all the events)
This is the code I wrote:
Take a close look to the part "element.value += text_array[i]".
function FillInText(element_id, text){
var element = $("#"+element_id);
element.focus();
element.click();
var kdown = jQuery.Event("keydown");
var kup = jQuery.Event("keyup");
var text_array = text.split("");
for(i = 0; i < text_array.length; i++){
var code = text_array[i].charCodeAt(0);
kdown.which = code;
kup.which = code;
element.trigger(kdown);
element.change();
element.value += text_array[i];
element.trigger(kup);
}
element.blur();
}
This code is perfect for any input and it works 99% of the time. But there is one input field, whose value isn't stored in its ".value" property. When I try to set/get the value using that, nothing returns.
However, I CAN get it using JQuery's "val()" function.
But whats perfect about "Element.value" is that you can ADD some value to the existing one. As far as I know, you can't do that with "val()".
Althought you could use:
val(function(index,currentvalue){
return currentvalue + text_array[i];
});
The code undestands it like:
previousValue is "a" and addedValue is "b".
The input field was "a", it takes the "b" and adds it together, then puts in into the input. so it doesn't ADD "a", but rather deletes the existing and then adds "ab" to it. When using "element.value += 'b'", it doesn't even touch the previousValue, instead it just adds it to it.
I would want a function that's like:
element.val() += "b";
I hope you can understand my problem... I'm sorry if I have explained it badly.
I don't think your code should work for any inputs.
.value is a DOM property, but element contains a jQuery object, not a DOM element. You can get the corresponding DOM element by indexing it:
element[0].value += test_array[i];
You can add to the value with jQuery .val() by using a function:
element.val(function(_, old_value) {
return old_value + test_array[i];
}
In general jQuert's selector like $("#element") is an array contains element(s), e.g. [DOMElement, DOMElement,...] and to use pure Java Script properties or methods use $("#element")[0]
https://www.w3schools.com/jquERY/jquery_ref_selectors.asp
But in pure JS document.getElementById("element") is pure element object.
https://www.w3schools.com/jsref/dom_obj_all.asp
Check this
//jQuery's prototype
jQuery.fn.FillInText = function(text) {
var el = $(this),kc,kd,ku
el.focus().click();
for(var i=0;i < text.length;i++) {
kc = text.charCodeAt(i);
kd = jQuery.Event("keydown", { keyCode: kc });
ku = jQuery.Event("keyup", { keyCode: kc });
el.trigger(kd);
el.change();
el[0].value += text[i]; // + "b"
el.trigger(ku);
}
}
//Test listening to keyup, keydown events
$("#inp").on("keydown keyup", function(e) {
console.log(e.type + ": " + String.fromCharCode(e.keyCode))
})
//Go..
$("#inp").FillInText("This is test string")
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="inp" />

How to do something when backspace or delete is pressed

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);
}

How to detect if a user input has been repeated?

I'm trying to make hangman in javascript and I want to check if the user has used a letter already. I made a var letterGuessValue = to 0 and if they add an input it = 1. I know this would say know to everything if i got it to work (it doesn't even do anything) but am I on the right track maybe? Here's my code. http://jsbin.com/aWOnAfe/5/edit
I would say add an input to a list and whenever they add another input (aka letter), check this list to see if it is already in there. If it is, then its because they've already used that letter before. If not, then it is a new letter.
I don't see where the difficult part is.
http://jsfiddle.net/DerekL/jgqQ9/
Sample code
var used = {};
$("input").keyup(function(){
var val = this.value;
alert( used[val] ? "Used" : "Not used" );
this.value = "";
used[val] = true;
});
How it works
Assign true to used.LETTER when a letter is entered. Before assigning it though, if it was undefined then it hasn't been used. If it is true then it is used.
Sometimes developers tend to use an Array to record pressed keystrokes when doing key combinations, but in this case, iterating an Array would require both more memory and computation power. A simple object is an enough fit.
Use an array to store all of the used letters and function like this to add new ones.
var inputs = []
function addLetter(letter){
var used = false;
for(var i = 0; i < inputs.length; i++){
if(inputs[i] == letter){
used = true;
break;
}
}
if(!used){
inputs.push(letter);
}
}
The easiest way is to append each letter to a string, like this:
var letters = '';
var letterPressed = 'X'; // uppercase it if appropriate for your language
if (letters.indexOf(letterPressed) > -1)
{
// you already pressed it
}
else
{
letters += letterPressed;
}
You can also use an array to store your list of presses, although IMO that's overkill.

even.data is not change

here is my own practice demo, it works well as i expect. but when i use line 8 ( comment on my demo code ) instead of line 7 ,the input text values all change to 0 which is different than the result of demo i giving out.
i look at the jquery website it only gives me this
Description: An optional object of data passed to an event method when the current executing handler is bound.
i think the result of using line 8 or line 7 should be the same because of i is assigned to count object, but it is not. Could someone explain me about this question. by the way, if someone could refactor my code will be even more nicer THANKS!!
here is my code
var i = 0;
$("#aa").on("click", {
count : i
},
function(event) {
var div = $('<div/>');
var input = $('<input />').attr("value", event.data.count);
event.data.count++;
//i++;
var bt = $('<input />').attr({
type : "button",
value : "remove",
});
div.append(input);
div.append(bt);
var index = $("div").length;
if (index == 0) {
$("#aa").after(div);
} else {
$("div").last().after(div);
}
bt.on('click', function(event) {
$(this).parent().remove();
});
});
when the current executing handler is bound.
this is important thing in the section. So, the object will be created only once, during the time of binding the function with the click event. So, changing i will not change the value of event.data.
When you do
event.data.count++;
you are actually mutating the object and the state of the object will be retained. That is why it works.

Javascript character limit counter function for text input

I've made a counter with javascript that shows a user how characters are remaining (from a set limit) for some text input or text area. Here's the code:
<script type="text/javascript">
function CountRemaining()
{
var limit = 1000;
var count = document.getElementById('press-form-body').value.length;
document.getElementById('counter').innerHTML = ((limit-count) + " characters left");
var timer = setTimeout("CountRemaining()",50);
}
</script>
My abomination above works fine but my problem is that I need to use this multiple times and making a separate function for every time I need it would be impractical to say the least.
I tried this and it didn't work:
<script type="text/javascript">
function CountRemaining(string, targetcounter, limit)
{
var count = document.getElementById(string).value.length;
document.getElementById(targetcounter).innerHTML = ((limit-count) + " characters left");
var timer = setTimeout("CountRemaining()",50);
}
I then figured I put the wrong statement for the timer so I changed it to this but still didn't work:
var timer = setTimeout("CountRemaining(string, targetcounter, limit)",50);
I'm lost. Any help would be highly appreciated. Thank you!
I think a better idea would be to use the "onchange" event for those types of elements.
Basically as soon as the text area / text input loses focus and is changed, you can bind a function to count how many characters are left.
document.getElementById('press-form-body').onchange = function() {
// your stuff (double check this to make sure the "this" value is right
// use this as an example
document.getElementById(targetcounter).innerHTML = this.value.length - 1000
}
Another solution would be to use the "key" events to listen to any keypress in the inputs.
document.getElementById('press-form-body').onkeypress = function() {
// your stuff (double check this to make sure the "this" value is right
// use this as an example
document.getElementById(targetcounter).innerHTML = this.value.length - 1000
}
function limittxt()
{
var tval = document.getElementById('press-form-body').value;
tlength = tval.length;
set = 100;
remain = parseInt(set - tlength);
document.getElementById('counter').innerHTML = remain + " characters left";
if (remain <= 0) {
document.getElementById('press-form-body').value = tval.substring(0, tlength - Math.abs(remain)))
}
}
An call this function in the input element like the following :
<input type='text' onkeypress='limittxt()' onkeyup='limittxt()' onkeydown='limittxt()'>
I suppose the error is with following line:
var timer = setTimeout("CountRemaining(string, targetcounter, limit)",50);
Here i think it should come like:
var str = "CountRemaining(" + string + "," + targetcounter + "," + limit + ")";
var timer = setTimeout(str,50);
If you want to proceed along the lines of using the timer to run the function at regular intervals, then you would need code similar to the following (hat-tip to #Sameera Thilakasiri for the inspiration):
function CountRemaining(string, targetcounter, limit){
var count = document.getElementById(string).value.length;
document.getElementById(targetcounter).innerHTML = ((limit-count) + " characters left");
}
setInterval(function() {
// call the function for each of the inputs on the page you need a counter for
CountRemaining('press-form-body', 'counter', 1000);
// etc
}, 50);
However, I believe #amchang87's approach is better overall, so I recommend you go with that if possible.
Tracking the number of characters left is always a little difficult. A good event to use is keyup or keypress, but that doesn't cover text that is dragged and dropped into the element, so people end up using a timer.
If you have many elements to monitor, consider putting them into an array, then call the timer at each interval and check all of the elements. Be careful with performance though, running the function every 50 ms may sap quite a bit of browser performance so try to keep the processing to an absolute minimum.
That means caching whatever you can and keep the logic simple.
Edit
The run and stop methods below could be used to start the timer when particular elements get focus, then stop it when they lose focus. That way you aren't hogging resources when not required.
/Edit
var keyCountCheck = (function() {
var elementArray, timerRef;
return {
// Initialise once
init: function() {
var input, inputs;
// Initialise elementArray if hasn't been done already
// If adding and removing elements, create new aray
// instead each time.
if (!elementArray) {
elementArray = [];
inputs = document.getElementsByTagName('input');
for (var i=0, iLen=inputs.length; i<iLen; i++) {
input = inputs[i];
if (input.type == 'text') {
elementArray.push(input);
}
}
}
timerRef = window.setInterval(keyCountCheck.run, 50);
},
// Run timer
run: function() {
// If setInterval not running, start it
if (!timerRef) {
keyCountCheck.init();
}
var el;
for (var i=0, iLen=elementArray.length; i<iLen; i++) {
checkLength(elementArray[i]);
}
},
// In case there is a reason to stop this thing.
stop: function() {
if (timerRef) {
window.clearTimeout(timerRef);
timerRef = null;
}
}
};
}());
window.onload = keyCountCheck.init;
function checkLength(el) {
// Character limit can be set as a data- attribute or
// class or various other ways. This is the simple way
var limit = 10;
var msgEl = document.getElementById(el.id + '_limitMsg');
if (msgEl) {
msgEl.innerHTML = (limit - el.value.length) + ' characters left. ' + (new Date());
}
}
Some supporting HTML to play with:
<input id="i0" value="1"><span id="i0_limitMsg"></span>
<br>
<input id="i1" value="2"><span id="i1_limitMsg"></span>
<br>
<button onclick="keyCountCheck.stop()">stop</button>
<button onclick="keyCountCheck.run()">run</button>
setInterval(
function CountRemaining(string, targetcounter, limit){
var count = document.getElementById(string).value.length;
document.getElementById(targetcounter).innerHTML = ((limit-count) + " characters left");
},50
);
Tryout this way.
Basic concept of this solution,
var f = function() {function_name(arg1); };
setTimeout(f, msec);

Categories

Resources