jQuery .val() ignoring trailing decimal points - javascript

I am currently working on limiting the allowed input in a numeric text field. I check the length of the value of the input field, if it is >= to the maxlength attribute, don't input anything.
$('input[maxlength]').on('keyup', '', null, function(event) {
var ref = $(this),
val = ref.val();
if ( val.length >= this.maxLength && event.which != 8){
return false;
}
}
However, if the currently value of the field ends in a decimal (eg "4."), then the val() method returns "4", which throws off the whole process. How can I read the contents of the input field while including the trailing decimal points?
http://jsfiddle.net/n3fmw1mw/329/ (Type in '4.' and you'll see what I'm talking about.)
EDIT: I've tried something from Mr. Hill's suggestion and now I have this
$('input[maxlength]').on('keydown', '', null, function(event) { //enforce maxlength on all inputs, not just text inputs
var ref = $(this);
ref.attr('type','text');
var val = ref.val();
if ( val.length >= this.maxLength && event.which != 8){
ref.attr('type','number');
return false;
}
ref.attr('type','number');
});
But now nothing is being inserted into my text box, even if debugging and seeing that we aren't returning false.

The decimal is being dropped because your input type is number. Set your input type to text.
<input type="text" id="textbox1"/>
Here's a working fiddle.
EDIT
Based on your new requirement of not being able to change the source, the code below should get you pointed in the right direction.
jQuery does not allow you to change the type of an element. To do it, you must remove the element and add one of the correct type in its place. The code below does just that.
Note: In an effort to make the code more reusable, I added a class to your element and then edited all elements with that particular class.
// Add class to identify that element type needs changed
$("#textbox1").addClass("numberToText");
// Swap number type input with text
$('.numberToText').each(function() {
$("<input type='text' />").attr({
id: this.id,
name: this.name,
value: this.value
}).insertBefore(this);
}).remove();
$("#textbox1").keyup(function() {
$('#log').append("Value: " + $('#textbox1').val() + '<br/>');
});
$(".button").click(function() {
$('#log').append("Value: " + $('#textbox1').val());
})
Here's a working fiddle.

Related

Basic JS: Adding characters at cursor position, while maintaining cursor position

Say I am making a basic Calculator that allows whole expressions to typed by the user. I'll use a simple <input> tag.
The user can type whatever they want, but I want to make it even easier for the client, I want to add a closing parenthesis immediately after they type (, so I set up my javascript to detect when ( is input by into the input field, then += a ) to the input field.
The problem with my code is that it adds the parenthesis to the end of the input, regardless of where they type the parenthesis, even at the beginning.
How can I add a character where ever the cursor is?
My code is as follows:
input = document.querySelector("input[type=text]");
input.addEventListener(`keyup`, (event)=>
{
if(event.key === `(`)
{
input.value+=`)`;
}
});
<input type="text" placeholder="Put mathematical expression"></input>
I believe that should solve your problem.
let input = document.querySelector("input[type=text]");
input.addEventListener(`keyup`, (event) => {
if(event.key === '(') {
let cursorPos = input.selectionStart;
input.value = input.value.substr(0, cursorPos) + ')' +
input.value.substr(cursorPos);
}
});

Input type number: how to detect if value was incremented or decremented?

Up until now, I simply used "change" to see if an input field of the type "number" was changed. However, now I need to know if the number was incremented or decremented to perform different actions. How can I see how the number was changed?
Looking for solutions with JQuery, but plain old JavaScript is fine as well.
You could simply previously store the value of your input and compare it on change :
let value = $('#test').val();
$('#test').on('change',function(){
if($(this).val() > value){
console.log('Input was incremented');
}else{
console.log('Input was decremented');
}
value = $(this).val();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" id="test" value="0">
You'll want to make use of a variable outside of your change function to keep track of the last value that was entered. Inside of your change function, simply compare against this value to find out whether the new value is higher or lower. Don't forget to update the previous value after the check!
This can be seen in the following:
let previous_value;
document.getElementById("input").addEventListener("change", function() {
let value = document.getElementById("input").value;
if (previous_value > value) {
console.log("Decreased");
} else if (previous_value < value) {
console.log("Increased");
}
previous_value = value;
});
<input type="number" id="input">
Along with the suggestions made of storing the previous value in memory in the JS, you could also store it on the input element itself, as a data attribute. That way JS from anywhere in your application will know the previous value, without having to have access to a variable
<input class="spinner" type="number" data-prev-value="0" />
$('.spinner').on('change', (e) => {
let direction = e.target.value > parseInt(e.target.dataset.prevValue) ? 'up' : 'down'
e.target.dataset.prevValue = e.target.value;
console.log(direction);
})
Whilst the answers above do what the OP requested, it is also worth noting that the input field of type "number" can be changed by user input as well as by the arrows. Hence, although you know the direction, you will not neccessarily know how much the item has been incremented or decremented.
This function will show a positive or negative number (so doing what the OP requested) but also show the amount incremented or decremented:
let value = $('#test').val();
$('#test').on('change', function() {
change = $(this).val() - value;
value = $(this).val();
console.log(change);
});
let value = input.value;
input.onchange = () => {
if (input.value > value) {
value++;
console.log('increase');
}
if (input.value < value) {
value--;
console.log('decrease');
}
};

Insert character at Cursor position in VUE JS

I have been trying to insert emoji in textarea exactly where the cursor is at. I looked around how tos in the web could not find anything specific in VUE JS. Most of them are in plain JS.
I have this Code
<div class="picker" v-show="showPicker">
<click-outside :handler="handleClickOutside">
<picker
set ="messenger"
title="Pick your emoji…"
emoji="point_up"
#click="addEmoji"
:emoji-size="16"
>
</picker>
</click-outside>
</div>
<textarea id="greeting_text_input" class="form-control"
type="text"
v-model="greeting_text"
rows="8"
required
placeholder="Hi {first-name}! Welcome to our bot. Click on the ‘Get
Started’ button to begin
">
</textarea>
My Method
addEmoji(emoji){
this.greeting_text += emoji.native;
this.showPicker = !this.showPicker;
}
Obviously, this code will add the character (emoji, in my case) to the last of the string. I need a pure vuejs solution for this.
What would be the best practise for this kind of problem in Vue? as there are few solutions in the web that based either in vanilla JS or Jquery.
Two steps:
1 get textarea element using a vue-way:
1.1 Add ref attrbute to textarea tag in your template code:
<textarea ref="ta"></textarea>
1.2 get this element after mounted hook of this component:
let textarea = this.$refs.ta
2 get cursor position of textarea element.
let cursorPosition = textarea.selectionStart
Here is reference: ref
<!-- tag -->
<textarea ref="yourTextarea" v-model.trim="txtContent" ......></textarea>
// methods:
insertSomething: function(insert) {
const self = this;
var tArea = this.$refs.yourTextarea;
// filter:
if (0 == insert) {
return;
}
if (0 == cursorPos) {
return;
}
// get cursor's position:
var startPos = tArea.selectionStart,
endPos = tArea.selectionEnd,
cursorPos = startPos,
tmpStr = tArea.value;
// insert:
self.txtContent = tmpStr.substring(0, startPos) + insert + tmpStr.substring(endPos, tmpStr.length);
// move cursor:
setTimeout(() => {
cursorPos += insert.length;
tArea.selectionStart = tArea.selectionEnd = cursorPos;
}, 10);
}
I learned about setSelectionRange from a different question, and I used it to handle credit card number input. I will show my solution here so a person can perhaps become inspired by it.
template:
<input
ref="input"
v-model="value"
#input="handleChange"
>
instance methods:
data() {
return {
lastValue: '',
}
},
methods: {
setCursorPosition(el, pos) {
el.focus();
el.setSelectionRange(pos, pos);
},
handleChange() {
// handle backspace event
if (this.value.length < this.lastValue.length) {
this.lastValue = this.value;
this.$emit('input-changed', this.value);
return;
}
// handle value-edit event
if (this.$refs.input.selectionStart < this.value.length) {
const startPos = this.$refs.input.selectionStart;
this.value = this.value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ').trim();
this.$nextTick(() => this.setCursorPosition(this.$refs.input, startPos));
this.lastValue = this.value;
this.$emit('input-changed', this.value);
return;
}
// handle everything else
this.value = this.value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ').trim();
this.lastValue = this.value;
this.$emit('input-changed', this.value);
},
},
The goal with the above code is to add spaces into a credit card input, so 1234123412341234 is automatically reformatted to 1234 1234 1234 1234. A person venturing into this territory will notice that problems arise when editing the input value.
You can see there are three conditions in my sample above. The last one is the default which simply reformats the current value with a 2-step combo: remove all spaces then adds a space every 4th character.
If you comment out the two if blocks, you can watch the problems emerge.
The first if block handles the backspace event. As you can see, every time the input changes, the value is captured as this.lastValue. When you press backspace, the goal of the first condition is to NOT run the regex. In my opinion, this is better UX. If you comment out that condition, you can see.
The second if block handles the editing events. A good way to test it, is to enter a valid CC but omit the 3rd character, so that everything is off by one. Then add the character in. Everything should be good. Likewise if you backspace multiple characters out. The goal of the second condition is to properly manage the cursor position (or caret position if you prefer that nomenclature).
You can safely delete the first condition and all references to lastValue and the code will still work. This is arguably simpler but worse UX.

Detect first character in textfield with Jquery

I'd like to know how to do the following with Jquery:
I have 1 textfield in a form.
Whenever the first character is a number, change the attr name of this field to 'number'. If the first character is a letter, change this attr name to 'letter'.
!! This also has to work when a number or text is copy-pasted into the field.
Thanks!
Jeroen
Bind (some) event(s) to the text field: The keyup event is used to update the name attribute when the user modifies the text (including shortcut CTRL+V copy-pasting), the paste and mousemove events are used to deal with copy-pasting (dragging, contextmenu).
$("#your-input").bind("keyup paste mousemove", function() {
var char = this.value.charAt(0); // Use vanilla JavaScript to get the
// first character of the text field
if (/[0-9]/.test(char)) { // Test against a pattern: digit
$(this).attr("name ", "number");
} else if (/[a-zA-Z]/.test(char)) { // Else, pattern: letters
$(this).attr("name", "letter");
} else { // Finally, no name?
$(this).attr("name", "");
}
});
Remove else {...}, and replace else if(/[a-zA-Z]/.test(char)) { with else { if you want the default name to be letter.
Something like this:
$("#yourformid").submit(function(){
var input = $("#yourinputid"),
val = input.val();
input.attr("name", /^\d/.test(val) ? "number" :
/^[A-Z]/i.test(val) ? "letter" : "");
});
It's difficult to handle paste in all browsers, but if you just set the attribute when the form is submitted you're covered no matter what the user does including drag'n'drop changes to the field. (Obviously I'm assuming it doesn't matter what the attribute is before submit.)

Show field if true, hide field if false?

Want to have a notification box displayed if amount in fieldA is higher than amount in fieldB.
Currently have some code working but the notification box toggles on and off not depending on the actual amount.
What am I missing?
jquery:
$(document).ready(function() {
$('#fieldA').change(function(){
if($(this).val()>$('#fieldb').val()){
//display it on the form
$('.labelNotification').toggle();
$('.labelNotification').append('Not recommended to have FieldA figure higher than FieldB.');
}
})
});
HTML:
< p style="display: none;" class="error labelNotification">
This is tailor-made for the toggle(boolean) method. Also, you have to be careful about appending to the notification label ... what if the user changes his answer twice? It's better to have multiple notification objects, each of which can contain stuff for a single type of notification.
$(function() {
$('#fieldA').change(function() {
var isLarger = +$(this).val() > +$('#fieldB').val(); // Note: convert to number with '+'
var $labelNotification = $('.labelNotification');
$labelNotification.toggle(isLarger);
if (isLarger) {
//display it on the form
$labelNotification.html('Not recommended to have FieldA figure higher than FieldB.');
}
})
});
If you're comparing numerical values (which it seems like you are), you should use parseInt or parseFloat to convert the (string) value returned by val() to an integer. According to the documentation for val, the function always returns a string value.
I found the problem ,
First thing is you need to have semicolon properly as below
$('#fieldA').change(function () {
if ($(this).val() > $('#fieldB').val()) {
alert("its greater");
//display it on the form
$('.labelNotification').append('Not recommended to have FieldA figure higher than FieldB.');
$('.labelNotification').show();
}
else {$('.labelNotification').hide();
$('.labelNotification').html('');}
});
Second thing , when you toggle it it won't show for the second time
if 40 > 30
and again if you entery 50 and 50 > 30 it won't show
this is second problem
final problem is empty the label all the time
$('.labelNotification').html('')'
Toggle is not the best approach for your situation.
You want to compare and then decide.
Since you are looking at numbers I would strongly suggest using a number type to do the comparison, either using parseInt() or parseFloat().
The text in the notification label only needs to be set once, since you don't have any comment for it showing something when B > A. I would suggest setting this in your HTML.
<span class="labelNotification" style="display:none">Your Warning Text</span>
<!-- if your CSS class has `display:none` remove the style attribute -->
as for the jQuery.
$(function() {
$("#fieldA").change(function() {
var a = parseInt($(this).val());
var b = parseInt($("#fieldb").val());
// handle if a or b is not a number --> isNaN(a) || isNaN(b)
if( a > b ) {
$('.labelNotification').show()
} else {
$('.labelNotification').hide()
}
});
});

Categories