HTML input event called twice - javascript

I have a problem with html/javascript code, the code should format numbers taken from keyboard (1 -> 0.01, 2-> 0.12, 3->1.23 ... 6->1,234.56).
It seems that the result of substring and substr is appended twice. In debug it works fine but without debug it doesn't. (1 -> 0.011, 2->1.122, 3->112.233)
It works the same for delete or backspace.
Here is the code:
formatElementAmount = function(f, d) {
d = d.replace(/\./g, '');
d = d.replace(/\,/g, '');
d = parseFloat(d);
d = d + '';
var c = document.getElementById((f.target || f.srcElement).id);
var b = '0123456789';
var a = f.which || f.keyCode;
if (a == 13) { // keycode 13 = enter >
return false;
}
if (a == 9) { // keycode 9 == tab
return true;
}
if (a == 8 || a == 46) { // keyCode 8 == backspace, 46 == delete
if (d.length > 0) {
d = d.substring(0, d.length - 1);
c.value = '';
}
c.value = format(d);
return false;
}
if (c.value.length > 12) {
c.value = '';
c.value = format(d);
return false;
}
if (a >= 96 && a <= 105) { // 96 = numbpad 0, 105 = numpad 9
a = a - 48;
}
key = String.fromCharCode(a);
if (b.indexOf(key) == -1) {
return false;
}
if ((d.length == 0) && (key == '0')) {} else {
d = d + key;
}
c.value = '';
c.value = format(d);
return false;
};
format = function(f) {
if (f.length == 0) {
return '0.00';
}
if (f.length == 1) {
return '0.0' + f;
}
if (f.length == 2) {
return '0.' + f;
}
var a, b, c, d, e;
if (f.length > 2) {
a = '';
for (c = 0, d = f.length - 3; d >= 0; d--) {
if (c == 3) {
a += ',';
c = 0;
}
a += f.charAt(d);
c++;
}
b = '';
len2 = a.length;
for (d = len2 - 1; d >= 0; d--) {
b += a.charAt(d);
}
e = f.substr(f.length - 2);
b += '.' + e;
}
return b;
};
<input id="paymentForm" name="paymentForm" type="text" value="0.00" onkeydown="if(this.value =='') this.value ='0.00';
if (!formatElementAmount(event, this.value)) {
event.stopPropagation();
}"></input>

The problem with your current code is it doesn't prevent the default action of the keyDown event:
if (!formatElementAmount(event, this.value)) {
event.stopPropagation();
event.preventDefault();
}

First of all your should stop using event.stopPropagation() - it doesn't stop default event. Also don't use event.preventDefault() which is not recommended. Instead use return false which disable default event effect and stop insert chars from keyboard.
Also use keypress event instead of keydown (I can't explain why it works because I don't know).
<input id="paymentForm" name="paymentForm" type="text" value="0.00" onkeypress="if(this.value =='') this.value ='0.00';
if (!formatElementAmount(event, this.value)) {
return false;
}"></input>
I tested this fix in Firefox, IE10 & Edge which i actually have on my computer.

Related

Making a date mask react with javascript: If i press simultaneous numbers i lost the mask

I'm trying to make a mask react date dd/mm/yyyy to a custom date input.
If i press the keys slow, the mask is setted correct dd/mm/yyyy, but supposing i press the numbers rapid, my mask is breaking
This is my component:
<DateInput
name="date"
placeholder="Data"
value={this.props.data}
dateFormat="DD/MM/YYYY"
onChange={this.props.changeDataTarefa}
animation="none"
onKeyUp={() => this.props.changeDataTarefaMask(this.fixDatePattern(this.props.data))}/>
this is my functions:
fixDatePattern(currDate) {
var currentDate = currDate;
if (currentDate){
var currentLength = currentDate.length;
var lastNumberEntered = currentDate[currentLength - 1];
}
if (!this.isNumber(lastNumberEntered) && currentDate) {
return currentDate.substring(0, currentLength - 1);
}
if (currentLength > 10) {
return currentDate.substring(0, 10);
}
let dateCountTracker = 0
if (currentLength == 1 && currentDate > 1) {
var transformedDate = "0" + currentDate + '/';
dateCountTracker = 2;
currentLength = transformedDate.length;
return transformedDate;
} else if (currentLength == 4 && currentDate[3] > 3) {
let transformedDate = currentDate.substring(0, 3) + "0" + currentDate[3] + '/';
dateCountTracker = 5;
currentLength = transformedDate.length;
return transformedDate;
} else if (currentLength == 2 && (dateCountTracker != 2 && dateCountTracker != 3)) {
dateCountTracker = currentLength;
return currentDate + '/';
} else if (currentLength == 5 && (dateCountTracker != 5 && dateCountTracker != 6)) {
dateCountTracker = currentLength;
return currentDate + '/';
}
dateCountTracker = currentLength;
return currentDate;
}
isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
Instead of using keyup, use keypress event on input. And you could also use react input mask plugin for same.
You can use below code for key press event and please check working stackblitz demo.
render() {
return (
<div>
<span>Date : </span>
<input type="text" maxLength="10" placeHolder="dd/mm/yyyy" onKeyPress={this.onKeyPress}/>
</div>
)
}
onKeyPress(e){
let input = e.target;
if(e.charCode < 47 || e.charCode > 57) {
e.preventDefault();
}
var len = input.value.length;
if(len !== 1 || len !== 3) {
if(e.charCode == 47) {
e.preventDefault();
}
}
if(len === 2) {
input.value += '/';
}
if(len === 5) {
input.value += '/';
}
}
You could use below react input mask plugins to achieve requirement.
imaskjs and react-input-mask

Javascript keydown event doesn´t give me the char # in EDGE

I'm working in a mentioning directive, basically when the user is typing in the input field ( a div with contentEditable=true in this case ), is gonna display a list of user for then insert the name of the user in a specific format, now the list is gonna displayed after the user press #, for chrome and firefox work just great but for EDGE and IE ( unfortunately i need to support ) doesn't work because in this case the # apparently doesn't exist.
now for the key press I'm using the #HostListener('keydown', ['$event'])
HostListener
#HostListener('keydown', ['$event']) keyHandler(event: any, nativeElement: HTMLInputElement = this._element.nativeElement) {
let val: string = getValue(nativeElement);
let pos = getCaretPosition(nativeElement, this.iframe);
let charPressed = this.keyCodeSpecified ? event.keyCode : event.key;
if (!charPressed) {
let charCode = event.which || event.keyCode;
if (!event.shiftKey && (charCode >= 65 && charCode <= 90)) {
charPressed = String.fromCharCode(charCode + 32);
} else if (event.shiftKey && charCode === KEY_2) {
charPressed = this.triggerChar;
} else {
charPressed = String.fromCharCode(event.which || event.keyCode);
}
}
if (event.keyCode == KEY_ENTER && event.wasClick && pos < this.startPos) {
// put caret back in position prior to contenteditable menu click
pos = this.startNode.length;
setCaretPosition(this.startNode, pos, this.iframe);
}
// console.log('=== keyHandler', this.startPos, pos, val, charPressed, event);
this.triggerList(event, charPressed, nativeElement, val, pos);
}
Now as you can see I'm using event.keycode and event.key to get the key from the event keydown, I pass does values to the method this.triggerList()
that basically is gonna display the list of mentions options if and only if the user press # that is the trigger char ( this.triggerChar ).
TriggerList Method
private triggerList(event, charPressed, nativeElement, val, pos): any {
if (charPressed == this.triggerChar) {
this.startPos = pos;
this.startNode = (this.iframe ? this.iframe.contentWindow.getSelection() : window.getSelection()).anchorNode;
// console.log('=== HERE CHAR', this.startNode, this.startPos);
// check if mentioning is allowed based on the text before the mention start char
if (!this.configService.appConfig.platform.EDGE) {
let position = this.getHtmlCaretPosition(nativeElement);
const charBefore = val[position - 1];
if (charBefore == undefined || charBefore.trim() == '' || charBefore == ':') {
this.log.trace('Start mentioning');
this.stopSearch = false;
this.searchString = null;
this.showSearchList(nativeElement);
this.updateSearchList();
}
} else {
this.stopSearch = false;
this.searchString = null;
this.showSearchList(nativeElement);
this.updateSearchList();
}
} else if (this.startPos >= 0 && !this.stopSearch) {
if (pos <= this.startPos) {
this.searchList.hidden = true;
}
// ignore shift when pressed alone, but not when used with another key
else if (event.keyCode !== KEY_SHIFT && !event.metaKey && !event.altKey && !event.ctrlKey && pos > this.startPos) {
if (event.keyCode === KEY_SPACE) {
this.startPos = -1;
} else if (event.keyCode === KEY_BACKSPACE && pos > 0) {
pos--;
if (pos == 0) {
this.stopSearch = true;
}
this.searchList.hidden = this.stopSearch;
} else if (!this.searchList.hidden) {
if (event.keyCode === KEY_TAB || event.keyCode === KEY_ENTER) {
this.stopEvent(event);
this.searchList.hidden = true;
// value is inserted without a trailing space for consistency
// between element types (div and iframe do not preserve the space)
let textValue = this.mentionSelect(this.searchList.activeItem);
insertValue(nativeElement, this.startPos, pos, textValue, this.iframe);
this.emitSelection(nativeElement);
if (this.htmlStyling) {
let quillElement = document.querySelector('.ql-editor');
let innerHtml = quillElement.innerHTML;
let strings = innerHtml.split(textValue);
if (strings.length === 2) {
innerHtml = `${strings[0]}<span id="mention${textValue.substring(1)}${strings.length - 1}" style="color: #0065FF; background: rgba(0,101,255,.2)">${textValue}</span> ${strings[1]}`;
} else {
let openSpan = false;
innerHtml = strings.reduce((total, current, currentIndex) => {
if (current.indexOf(`mention${textValue.substring(1)}`) > 0) {
return `${total}${openSpan ? '</span> ' : ''}${current}${textValue}`;
} else if (openSpan) {
return `${total}</span> ${currentIndex < strings.length - 1 ? current + textValue : current}`;
} else {
openSpan = true;
return `${total}${current}<span id="mention${textValue.substring(1)}${strings.length - 1}" style="color: #0065FF; background: rgba(0,101,255,.2)">${textValue}`;
}
}, '');
}
quillElement.innerHTML = innerHtml;
// tslint:disable-next-line:no-angle-bracket-type-assertion
let mentionElement: HTMLInputElement = document.getElementById(`mention${textValue.substring(1)}${strings.length - 1}`) as HTMLInputElement;
// tslint:disable-next-line:no-angle-bracket-type-assertion
setCaretPosition(mentionElement.nextSibling as HTMLInputElement, 1);
}
// fire input event so angular bindings are updated
if ('createEvent' in document) {
let evt = document.createEvent('HTMLEvents');
evt.initEvent('input', false, true);
nativeElement.dispatchEvent(evt);
}
this.startPos = -1;
return false;
} else if (event.keyCode === KEY_ESCAPE) {
this.stopEvent(event);
this.searchList.hidden = true;
this.stopSearch = true;
return false;
} else if (event.keyCode === KEY_DOWN) {
this.stopEvent(event);
this.searchList.activateNextItem();
return false;
} else if (event.keyCode === KEY_UP) {
this.stopEvent(event);
this.searchList.activatePreviousItem();
return false;
}
}
if (event.keyCode === KEY_LEFT || event.keyCode === KEY_RIGHT) {
this.stopEvent(event);
return false;
} else {
let mention = val.substring(this.startPos + 1, pos);
if (event.keyCode !== KEY_BACKSPACE) {
mention += charPressed;
}
this.searchString = mention;
this.searchTerm.emit(this.searchString);
this.updateSearchList();
}
}
}
}
now the issue here is that if the user to insert the char # need to use the combination of ALT + Q EDGE only detect ALT and then Q, compare to firefox and chrome that with the combination ALT + Q detect # for this reason the list is not display because the char never match.
First i replace the event keydown for keypress, then where i save the char in the variable charPress i create a condition to check if the browser is EDGE or IE, and get char code using event.charCode and convert it in to string using String.fromCharCode(event.charCode) at the end looks like this.
#HostListener('keypress', ['$event']) keyHandler(event: any, nativeElement: HTMLInputElement = this._element.nativeElement) {
let val: string = getValue(nativeElement);
let pos = getCaretPosition(nativeElement, this.iframe);
let charPressed = this.keyCodeSpecified ? event.keyCode : event.key;
if (this.configService.appConfig.platform.EDGE) {
charPressed = String.fromCharCode(event.charCode);
}
......

Format Input to 2 Decimals while Typing HTML/Javascript

How can I create an input field for currency? I'm looking for it to work as follows:
Initial: 0.00
Type "1": 0.01
Type "2": 0.12
Type "5": 1.25
I'm pretty new with web design, so I'm looking for a simpler solution. I saw a similar question & answer to this question with an Angular solution, but I'm unsure how to implement that into my HTML project. I have a simple folder with HTML files in it. Thanks!
A little tricky
Working Demo
document.getElementById("demo").onkeydown = function (e) {
//console.log(e.keyCode);
if (e.keyCode != 37 && e.keyCode != 39 && e.keyCode != 8 && e.keyCode != 46)
e.preventDefault();
if (e.keyCode == 8 || e.keyCode == 46) {
//If already key down (backspaceOrDel=1) then no affect
if (backspaceOrDel == 1)
e.preventDefault();
else
backspaceOrDel = 1;
return;
}
if (e.keyCode < 48 || (e.keyCode > 57 && e.keyCode <96) || e.keyCode > 105 )
return;
try {
var val = this.value;
var val1 = 0;
if (val == 0) {
val1 = e.key / 100;
}
else {
//very tricky. We needed val1=val*10+e.key but it does not
//work correctly with floats in javascript.
//Here you have to different than android in logic
var val1 = parseFloat(val) * 1000;
val1 += parseFloat(e.key);
val1 = val1 / 100;
}
val1 = val1.toFixed(2);
if (!isNaN(val1))
this.value = val1;
}
catch (ex) {
alert("Invalid Amount");
}
};
<style>
.amount_tendered {
text-align: right;
font-size: 24px;
width: 200px;
}
</style>
<form>
<input class="amount_tendered" id="text" type="number" min="0" value="0.00" onkeyup="formatNum(this);" onclick="this.select(); activated();">
</form>
<script type="text/javascript">
String.prototype.splice = function(idx, rem, str) {
return this.slice(0, idx) + str + this.slice(idx + Math.abs(rem));
};
function formatNum(obj){
var str = obj.value;
switch (true){
case str.length==1:
str = '0.0' + str;
break;
case str.length==3:
str = '0' + str;
}
var indices = [];
for(var i=0; i<str.length;i++) {
if (str[i] === "." && (str.length - i)!=3) indices.push(i);
}
for(var i=0; i<indices.length;i++) {
str = str.replace('.','');
}
indices = [];
for(var i=0; i<str.length;i++) {
if (str[i] === ".") indices.push(i);
}
if (indices.length==0){
str = str.splice(str.length-2, 0, ".");
}
if (str[0]=='0' && str[1]!='.'){
str = str.replace('0','');
}
obj.value = str;
}
</script>

Show last three characters of a password with angularJS

I'm currently developping a mobile app with Ionic framework and AngularJS.
In my login page, the user's account name is loaded on his second connection (and is considered as a password field). However, this user can have multiple accounts. What I've been asked is to show the last three characters of this login.
I would have wanted to use something like a filter, but it doesn't seem to work on inputs ...
Then I've been looking into angularJS directives, and I've been struggling for a few days now, trying many things.
The main problem i'm encountering when doing something like
app.directive("editor", function(){
return {
require: "?ngModel",
scope: true,
template: "<input ng-model='value' ng-change='onChange()'>",
link: function(scope, element, attrs, ngModel){
if (!ngModel) return;
scope.onChange = function(){
/* process coded value here */
ngModel.$setViewValue(scope.value);
};
ngModel.$render = function(){
/* Or process coded value here */
scope.value = ngModel.$modelValue;
};
}
};
});
With this directive, I manage to have my controller value changed, but I would like only to have my view value changed.
I would really appreciate your help, AND your explanations !
I tried to do what you want. And it looks like I got.
Perhaps this is not a complete solution, but it works.
And I have not tested it in mobile browser and Safari.
You may need to modify it a bit.
Live example on jsfiddle.
angular.module('ExampleApp', [])
.controller('firstCtrl', function($scope) {
$scope.sampleItem = {
sampleName: "1234"
};
$scope.change = function(val) {
console.log(val);
}
})
.directive("useModel", ["SelectManager",
function(SelectManager) {
return {
restrict: "A",
scope: {
useModel: "=",
useModelReplacment: "#",
useModelCharacterShow: "=",
useChange: "&"
},
link: function(scope, elem) {
if (!angular.isDefined(scope.useModelCharacterShow))
scope.useModelCharacterShow = 0;
if (scope.useModelReplacment == undefined)
scope.useModelReplacment = "*";
if (scope.useModel == undefined)
scope.useModel = "";
else
elem.val(getMaskValue(scope.useModel));
scope.$watch('useModel', function(val) {
elem.val(getMaskValue(val));
if (scope.useChange)
scope.useChange();
})
function getMaskValue(val) {
var maskVal = "";
for (var i = 0; i < val.length; i++) {
if (scope.useModelCharacterShow > 0) {
if (i >= scope.useModelCharacterShow)
maskVal += scope.useModelReplacment;
else
maskVal += val[i];
}
if (scope.useModelCharacterShow < 0) {
if (i < val.length + scope.useModelCharacterShow)
maskVal += scope.useModelReplacment;
else
maskVal += val[i];
}
if (scope.useModelCharacterShow == 0) {
maskVal += scope.useModelReplacment;
}
}
return maskVal;
}
function onKeyPressed(event) {
if (event.ctrlKey && (event.charCode == 99 || event.charCode == 118 || event.charCode == 97 || event.charCode == 120))
return true;
var key_code = event.charCode;
var input = event.srcElement || event.target;
var ch = String.fromCharCode(key_code);
var start = SelectManager._getSelectionStart(input);
var end = SelectManager._getSelectionEnd(input);
// console.log('start end', start,end);
scope.useModel = scope.useModel.substr(0, start) + ch + scope.useModel.substr(end);
// console.log('inner value onKeyPressed', scope.useModel);
scope.$apply();
//console.log('show value onKeyPressed', maskVal);
//input.value = getMaskValue(scope.useModel);
event.returnValue = false;
SelectManager._setSelection(input, start + 1, start + 1);
return false;
}
function onKeyUp(event) {
if (event.ctrlKey && (event.charCode == 99 || event.charCode == 118 || event.charCode == 97 || event.charCode == 120))
return true;
var key_code = event.keyCode;
if (!(key_code == 13 || key_code == 27 || key_code == 8 || key_code == 46))
return true;
var input = event.srcElement || event.target;
var start = SelectManager._getSelectionStart(input);
var end = SelectManager._getSelectionEnd(input);
// console.log('start end', start,end);
if (key_code == 8 && start == end) {
start--;
}
if (key_code == 46 && start == end) {
//start++;
end++;
}
//console.log('inner value keyup', scope.useModel);
scope.useModel = scope.useModel.substr(0, start) + scope.useModel.substr(end);
//console.log('inner value keyup', scope.useModel);
scope.$apply();
//input.value = getMaskValue(scope.useModel);;
event.returnValue = false;
SelectManager._setSelection(input, start, start);
return event.returnValue;
}
function onKeyDown() {
var key_code = event.keyCode;
if (!(key_code == 13 || key_code == 27 || key_code == 8 || key_code == 46))
return true;
event.returnValue = false;
return event.returnValue;
}
function onPaste(event) {
var input = event.srcElement || event.target;
var ch = "";
if (event.type == "drop") {
event.returnValue = false;
return false
}
if (event.type == "paste")
ch = event.clipboardData.getData("text");
var start = SelectManager._getSelectionStart(input);
var end = SelectManager._getSelectionEnd(input);
// console.log('start end', start,end);
scope.useModel = scope.useModel.substr(0, start) + ch + scope.useModel.substr(end);
// console.log('inner value onKeyPressed', scope.useModel);
scope.$apply();
//input.value = getMaskValue(scope.useModel);
event.returnValue = false;
SelectManager._setSelection(input, start + ch.length, start + ch.length);
return false;
}
elem.on('keypress', onKeyPressed);
elem.on('keyup', onKeyUp);
elem.on('keydown', onKeyDown);
elem.on('paste drop', onPaste);
},
};
}
])
.service('SelectManager', function() {
return {
_getSelectionStart: function(obj) {
var p = 0;
if (obj.selectionStart) {
if (typeof(obj.selectionStart) == "number") p = obj.selectionStart;
} else if (document.selection) {
var r = document.selection.createRange().duplicate();
r.moveEnd("character", obj.value.length);
p = obj.value.lastIndexOf(r.text);
if (r.text == "") p = obj.value.length;
}
return p;
},
_getSelectionEnd: function(obj) {
var p = 0;
if (obj.selectionEnd) {
if (typeof(obj.selectionEnd) == "number") {
p = obj.selectionEnd;
}
} else if (document.selection) {
var r = document.selection.createRange().duplicate();
r.moveStart("character", -obj.value.length);
p = r.text.length;
}
return p;
},
GetXY: function(obj) {
var x = 0;
var y = 0;
while (obj.offsetParent) {
x += obj.offsetLeft;
y += obj.offsetTop;
obj = obj.offsetParent;
}
return {
X: x,
Y: y
};
},
_setSelection: function(obj, a, b) {
if (obj.setSelectionRange) {
obj.focus();
obj.setSelectionRange(a, b);
} else if (obj.createTextRange) {
var r = obj.createTextRange();
r.collapse();
r.moveStart("character", a);
r.moveEnd("character", (b - a));
r.select();
}
},
_Collapse: function(obj) {
var r = obj.createTextRange();
r.collapse();
}
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="firstCtrl">
use-model(first three) <input use-model="sampleItem.sampleName" use-change="change(sampleItem.sampleName)" use-Model-Character-Show="3">
<br> use-model(last three) <input use-model="sampleItem.sampleName" use-change="change(sampleItem.sampleName)" use-Model-Character-Show="-3">
<br> ng-model <input ng-model="sampleItem.sampleName">
<pre> {{sampleItem.sampleName}}</pre>
<button ng-click="sampleItem.sampleName='AAAAA'">
set AAAAA
</button>
</div>
</div>

Synchronous input update with selected digit in HTML/JavaScript

I'm trying to implement a customised input that can use left or right arrow key to select the digit and use up/down arrow key to increment/decrement the digit. Here's the code in jsfiddle: http://jsfiddle.net/uk5t3z4d/48/. However, I have two problems:
I cannot add digit using the number pad, the input always stays at X.XX
When I use another function I wrote (parseLocalFloat which is commented out), the output stops displaying anything, and I cannot use the left and right key to select the digit etc.
How can I overcome these two issues? Please shed a light on me, thanks!
HTML
<div class="display" id="out"></div>
<div class="form-group">
<label for="comment">value:</label>
<input class="form-control" type="text" value="0.00" id="in"></input>
</div>
JavaScript
function createSelection(field, start, end) {
if( field.createTextRange ) {
var selRange = field.createTextRange();
selRange.collapse(true);
selRange.moveStart('character', start);
selRange.moveEnd('character', end);
selRange.select();
} else if( field.setSelectionRange ) {
field.setSelectionRange(start, end);
} else if( field.selectionStart ) {
field.selectionStart = start;
field.selectionEnd = end;
}
}
function getLocalDecimalSeparator() {
var n = 1.1;
return n.toLocaleString().substring(1,2);
}
function parseLocalFloat(num) {
return +(num.replace(getLocalDecimalSeparator(), '.'));
}
var inputBox = document.getElementById('in');
//var inputBox = parseLocalFloat(document.getElementByID('in').value);
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = inputBox.value;
}
$('#in').on("keydown", function(e){
var gotCode = false;
var curPos = this.selectionStart;
var endPos = this.selectionEnd;
if(curPos !== endPos) {
createSelection(this, curPos, curPos+1);
}
// get the position
if(e.keyCode == 37){
curPos--;
gotCode=true;
}
if(e.keyCode == 39){
curPos++;
gotCode=true;
}
var before = $(this).val().substring(0,curPos);
var after = $(this).val().substring(curPos+1);
var cur = Number($(this).val().substring(curPos, curPos+1));
// avoid adding extra stuff
if(curPos < $(this).val().length) {
if(e.keyCode == 38) {
cur++;
if(cur > 9) cur = 0;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
if(e.keyCode == 40) {
cur--;
if(cur < 0) cur = 9;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
}
if(!gotCode) {
e.preventDefault();
return false;
}
var field = this;
window.setTimeout(function(){
createSelection(field, curPos, curPos+1);
}, 10);
});
as for the "get number keys to work":
as stated you need to add the keys you want to support:
if(e.keyCode >= 48 && e.keyCode <= 57) {
var num = e.keyCode - 48; // 0=48; 9=59
$(this).val(before + '' + num + '' + after);
gotCode = true;
e.preventDefault(); // otherwise a new number is added as well
}
(this needs to come before the if (!gotCode) ... )
as for the customFloat: the the response from Moishe
For #1:
if(!gotCode) {
e.preventDefault();
return false;
}
ensures that if gotCode is false the default event (which in this case is the default keydown event) will not occur.
gotCode only seems to be true if keyCode is equal to 37, 38, 39, or 40 (the arrow keys). You are essentially preventing the other keys (like number keys) from having any effect on the textBox.
You probably would like to enable the number keys (when shift or caps aren't on) and number pad keys.
Additionally, you may want to check that the cur is a number (and not .) before attempting to increment or decrement its value.
You could do:
var isNumberKey = (
( e.keyCode >= 48 //is more than or equal to 0 key
&& e.keyCode <= 57 //is less than or equal to 9 key
&& !e.shiftKey) //shift key or cap key not on
|| ( e.keyCode >= 96 //more than or equal to 0 key in number pad
&& e.keyCode <= 105)); //less than or equal to 9 key in number pad
if(!gotCode && !isNumberKey) { //not arrow key or number key
console.log(e);
e.preventDefault();
return false;
}
For #2:
var inputBox = parseLocalFloat(document.getElementByID('in').value);
is setting inputBox to whatever parseLocalFloat returns which happens to be a number.
This is problematic because you then attempt to attach a keyUp event to that number instead of the inputBox:
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = inputBox.value;
}
You may want to instead call parseLocalFloat on the number and set the out textBox's value to that:
var inputBox = document.getElementById('in');
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = parseLocalFloat(inputBox.value);
}
function createSelection(field, start, end) {
if( field.createTextRange ) {
var selRange = field.createTextRange();
selRange.collapse(true);
selRange.moveStart('character', start);
selRange.moveEnd('character', end);
selRange.select();
} else if( field.setSelectionRange ) {
field.setSelectionRange(start, end);
} else if( field.selectionStart ) {
field.selectionStart = start;
field.selectionEnd = end;
}
}
function getLocalDecimalSeparator() {
var n = 1.1;
return n.toLocaleString().substring(1,2);
}
function parseLocalFloat(num) {
return +(num.replace(getLocalDecimalSeparator(), '.'));
}
var inputBox = document.getElementById('in');
// var inputBox = parseLocalFloat(document.getElementByID('in').value);
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = parseLocalFloat(inputBox.value);
}
$('#in').on("keydown", function(e){
var gotCode = false;
var curPos = this.selectionStart;
var endPos = this.selectionEnd;
if(curPos !== endPos) {
createSelection(this, curPos, curPos+1);
}
// get the position
if(e.keyCode == 37){
curPos--;
gotCode=true;
}
if(e.keyCode == 39){
curPos++;
gotCode=true;
}
var $thisVal = $(this).val();
var before = $thisVal.substring(0,curPos);
var after = $thisVal.substring(curPos+1);
var cur = Number($thisVal.substring(curPos, curPos+1));
// avoid adding extra stuff
if(curPos < $thisVal.length && !isNaN(cur)) {
if(e.keyCode == 38) {
cur++;
if(cur > 9) cur = 0;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
if(e.keyCode == 40) {
cur--;
if(cur < 0) cur = 9;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
}
var isNumberKey = ((e.keyCode >= 48 && e.keyCode <= 57 && [16, 20].indexOf(e.keyCode) == -1 && !e.shiftKey) || (e.keyCode >= 96 && e.keyCode <= 105));
if(!gotCode && !isNumberKey) {
console.log(e);
e.preventDefault();
return false;
}
var field = this;
window.setTimeout(function(){
createSelection(field, curPos, curPos+1);
}, 10);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="display" id="out"></div>
<div class="form-group">
<label for="comment">value:</label>
<input class="form-control" type="text" value="0.00" id="in"></input>
</div>

Categories

Resources