I need to find a way to detect if a space was deleted or backspaced, and run a function if that is the case. I am working on this in JavaScript / jQuery.
I know I can get the delete or backspace key press by using:
$(this).keyup(function(event) {
event.keyCode
However, I do not know how to tell if the delete or backspace command removed a space?
Very appreciative for any suggestions.
See here: http://jsfiddle.net/Txseh/
(function(){
var currentWhitespaceCount;
$("input").keyup(function(e){
var newCount = ($(this).val().match(/\s/g) || []).length;
if (newCount < currentWhitespaceCount)
alert("You removed one or more spaces, fool.");
currentWhitespaceCount = newCount;
});
})();
It tracks the current number of whitespace characters in the input, and if ever the number goes down, it alerts(or does whatever you want).
Cache the value beforehand (set a value on keypress) and compare with the value after keypress. That is the only way to know with certainty that one or more spaces has been removed. Any checking of keys relies on you being able to work out what possible keys could achieve the removal of a space, and will likely leave holes.
As an example, selecting the final letter of a word and the space following it, if we press the last letter it will remove the space. But the key pressed is not backspace or delete.
Bind to the keydown and compare the value from before and after to see if it reduced in size.
$(input).keydown(function(){
var currVal = this.value, self = this;
setTimeout(function(){
if ( currVal.length > self.value.length ) {
console.log(currVal.length - self.value.length + " characters have been removed.");
}
},0);
});
http://jsfiddle.net/ymhjA/1/
Updated sample:
$("input").keydown(function() {
var currVal = this.value,
self = this;
setTimeout(function() {
if (currVal.length - self.value.length === 1) {
var origVal = $.grep(currVal.split(""),function(val){
return val === " ";
});
var newVal = $.grep(self.value.split(""),function(val){
return val === " ";
});
if ( origVal.length != newVal.length ) {
console.log("a space was removed");
}
}
}, 0);
});
http://jsfiddle.net/ymhjA/4/
actually here is my code http://jsbin.com/atuwez/3/edit
var input = $('#input'),
afterLength,
beforeLength;
input.on({
'keydown': function () {
beforeLength = input.val().split(/\s/).length;
},
'keyup': function(event) {
var key = event.keyCode || event.charCode;
if( key == 8 || key == 46 ) {
afterLength = input.val().split(/\s/).length;
console.log(beforeLength == afterLength);
}
}
});
Related
We have pin numbers in the following format:
45 674 25 910
Our original requirement was to give the users the ability to enter their pin with or without spaces,
In other words, if the pin is 10 digits without spaces, we would like to accept it as valid input.
Similarly, if the pin is 13 digits (with the three spaces) we would also like to accept the input as valid.
If the digits are less than 10 with or without spaces, or more than 13 with spaces, we would like to throw an error that input is invalid.
The script below satisfied the above requirements:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
$("#btnSearch").click(function () {
var result = true;
if ($('#pin').val().replace(/ /g, '').length == 10) {
result = true;
}
else {
result = false;
alert("Invalid");
return false;
}
return result;
});
});
</script>
However, management has decided to change the requirement to ask that spaces be automatically added while the user is entering the pin numbers.
In other words, users can enter the pin numbers with spaces or they can enter the pin numbers without spaces but that spaces be automatically added while they are typing the pin numbers.
Any ideas how to modify the script above?
Better yet, is there an example that I can modify to meet our requirements?
Using String.prototype.replace()
Note: this code will add space after 2, 3, 2, 3 ..etc chars. you can change the number of chars by edit the code inside map
$("#user-input").on('keyup', function () {
// Helpers
var swap = 4, // Swap between 3 and 4
index = 2; // Spaces indexs 2, 6, 9, 13 .. etc
// This variable contains the same input value with sapces
var niceVal = $(this).val()
.replace("/\s/g", "").split("") // Remove all spaces and convert to array
.map(function (item, i) { // loop throw the array
if (i === 0) {
return item;
}
if (i % index === 0) {
item = item === " "
? item
: " " + item;
index += swap;
swap = swap === 3
? 4
: 3;
}
return item;
}).join(""); // Convert array to string
$(this).val(niceVal); // Update input value
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="user-input">
Well with pure JS my approach to the problem could be as follows;
Though i mentioned the keyup event in my comment, it seems the keydown event turns out to be more appropriate since keyup might result a strange behavior when multiple keys are pressed at the same time due to speed typing. I haven't tested this thoroughly so it's just a guidance for you. However, if you discover any buggers i can possibly have a look into it.
Edit: Despite all my efforts I have come to the awareness of the fact that if you want to modify the value of an input element, like in this question, you must set up a logic to utilize both keydown and keyup events in a harmony. This will simplify your logic enormously and would yield a much sturdy code.
OK lets go...
var pin = document.getElementById("PIN"),
pbt = document.getElementById("PBT");
pin.addEventListener("keydown", function(e){
var val = e.target.value,
len = val.length,
lst = val[len-1],
key = e.key;
e.target.value = key === "Backspace" ? len === 4 ||
len === 8 ||
len === 11 ? val.slice(0,-1)
: val
: len === 2 ||
len === 6 ||
len === 9 ? val + "\xa0"
: val;
});
pin.addEventListener("keyup", function(e){
var val = e.target.value,
pix = val.search(/[^0-9\xa0]/); // problem index
e.target.value = ~pix ? val.slice(0, pix) : val
});
pbt.addEventListener("click", function(e){
pin.value.length === 13 ? console.log(pin.value)
: console.log("Please complete the PIN Code");
});
<input id="PIN" value="" placeholder="Enter PIN" maxlength=13 size=13/>
<button id="PBT">Enter PIN</button>
I have a textarea that contains new lines initialized by a number and a period:
<textarea autoFocus id="text-area"wrap="hard"
defaultValue ={this.state.textAreaVal} onKeyUp={this._editTextArea}/>
To illustrate this:
Line 1
Line 2
Line 3
I have a function that is called onKeyDown to check if the keycode is a backspace:
_editTextArea: function(event) {
var key = event.keyCode;
if (key == 8) {
//remove the whole line if the previous characters are a number followed by a period and then a space
} else {
return true;
}
},
My goal here is to delete the number and period with one backspace (how its done in microsoft word, imagine having an ordered list when you get to the bulletpoint or number or roman numeral and you press backspace, it not only deletes the whole list item but also it returns you to the previous list item's last char.
How can I accomplish this?
Try this, should give you enough to go on.
<p id="demo"></p>
<script>
function myFunction() {
var str = "Hello world! 12.";
while (str.substring(str.length-1) == "." || isNumber(str.substring(str.length-1)))
{
str = str.substring(0,str.length-1)
}
document.getElementById("demo").innerHTML = str;
}
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
</script>
I don't know exactly what you want but this maybe could help you:
$('textarea').keyup(function (e) {
if (e.keyCode == 8) {
e.preventDefault();
var lines = $('textarea').val().split('\n');
lines.splice(this.value.substr(0, this.selectionStart).split("\n").length-1, 1);
$('textarea').val(lines.join("\n"));
}
})
You can try it here:
https://jsfiddle.net/swnhe2f0/1/
I have been trying to allow numeric field and one decimal point in my Grid.Its work fine when its suitable for input box.
when i am calling onKeyPress the script work fine for "input box" rather than on "Div element"
In "Div element",when i am supposed to use this .It allow to access only for number rather Alphabet
hence,while coming to "decimal place" its not working as it should.[ It's allowing many Dot's]
<script>
function getKey(e)
{
if (window.event)
return window.event.keyCode;
else if (e)
return e.which;
else
return null;
}
function restrictChars(e, obj)
{
var CHAR_AFTER_DP = 2; // number of decimal places
var validList = "0123456789."; // allowed characters in field
var key, keyChar;
key = getKey(e);
if (key == null) return true;
// control keys
// null, backspace, tab, carriage return, escape
if ( key==0 || key==8 || key==9 || key==13 || key==27 )
return true;
// get character
keyChar = String.fromCharCode(key);
// check valid characters
if (validList.indexOf(keyChar) != -1)
{
// check for existing decimal point
var dp = 0;
if( (dp = obj.value.indexOf( ".")) > -1)
{
if( keyChar == ".")
return false; // only one allowed
else
{
// room for more after decimal point?
if( obj.value.length - dp <= CHAR_AFTER_DP)
return true;
}
}
else return true;
}
// not a valid character
return false;
}
</script>
<div onKeyPress="return restrictChars(event, this)">
Any Ideas how we could achieve it
For an <input>, it is required to check the value attribute, hence why obj.value is used in your code above. A div element doesn't have a value attribute. You have to check it's innerHTML (mdn docs). If you replace all instances of obj.value with obj.innerHTML, your code should work.
You need to use jQuery keypress() method to handle this right:
$("#d input").keypress(function(event){
return restrictChars(event);
});
See the working fiddle:
http://fiddle.jshell.net/ePvJ8/1/
I am trying to implement a simple javascript-html calculator. What i want to do is,typing only one '.' by the user. How can i control this ? Here is the code that i tried.
I can already find the number of '.' but i'am confused now also this replaceAll function is not replacing '.' with empty string.
String.prototype.replaceAll = function(search, replace)
{
//if replace is null, return original string otherwise it will
//replace search string with 'undefined'.
if(!replace)
return this;
return this.replace(new RegExp('[' + search + ']', 'g'), replace);
};
function calculate(){
var value = document.calculator.text.value;
var valueArray = value.split("");
var arrayLenght = valueArray.length;
var character = ".";
var charCount = 0;
for(i=0;i<arrayLenght;i++){
if (valueArray[i]===character) {
charCount += 1;
}
}
if(charCount>1){
var newValue=value.replaceAll(".","");
alert(newValue);
}
}
I recently accomplished this with the following code. This sat in a function that was triggered for each keypress on the field. It might be a bit messy and I'm sure there's a better way, but it works. It also allows someone to enter a "." if they have one selected, since it would replace that selected one:
// Function to verify number
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
// Function called (below) to get text if it is selected
function getSelectionText() {
var text = "";
if (window.getSelection) {
text = window.getSelection().toString();
} else if (document.selection && document.selection.type != "Control") {
text = document.selection.createRange().text;
}
return text;
}
// jQuery function on keypress for the textbox
$(".textbox").on("keypress", function (e) {
var fieldVal = $(this).val();
if (e.keyCode == 9) return true; // tab
var keyPressed = String.fromCharCode(e.keyCode);
if (keyPressed == "." && ((fieldVal.indexOf(".") == -1) || getSelectionText().indexOf(".") > 0)) return true; // decimal places, only allow one
return (isNumber(keyPressed));
});
EDIT: I should mention, the isNumber() function also checks to verify that the end result is a number. I can post that if you'd like also.
EDIT 2: Modified code block to add the isNumber() function.
Your (main) problem is this test :
if(!replace)
When replace is "", !"" is true.
Change the test to
if (replace==null)
(it works for both undefined and null)
But I don't really see why you need to define a replaceAll function when you seem to want
var newValue=value.replace(/\./g,"");
EDIT : If what you want is to replace all dots apart the first one you can do
var i=0, newValue=value.replace(/\./g, function(){ return i++ ? "," : "." });
(you don't need to count before that, and i will be the count of dots)
I have a JavaScript function that validates an input field and prevents the user from typing anything that doesn't match the condition. This function is based on event.keyCode.
I'm trying to modify the function to use a RegExp and validates not "per character" but "per whole input" so that it does the same, but with different conditions:
numeric only
allowed decimal "." or ","
Here is the function in its current form, using event.keyCode:
function isNumeric(evt, alertDIVid, alertMsg) {
var charCode = (evt.which) ? evt.which : event.keyCode
if (charCode >= 48 && charCode <= 57) {
document.getElementById(alertDIVid).innerHTML = '';
return true;
}
else {
document.getElementById(alertDIVid).innerHTML = alertMsg;
return false;
}
}
document.getElementById('AMNT').onkeypress = function(event) {
event = event || window.event;
return isNumeric(event, 'numericalert', 'Numeric values only!')
};
In order to do the kind of validation you want, you need to listen to the keyup event instead. This event fires after the field is changed, so that you know the new value of the field. You also need to know the previous value of the field so you can "reset" it if what the user typed turns out to be invalid.
For example:
(function() {
var previousValue = document.getElementById('myInput').value;
var pattern = /^\d*((\.|,)\d*)?$/;
function validateInput(event) {
event = event || window.event;
var newValue = event.target.value || '';
if (newValue.match(pattern)) {
// Valid input; update previousValue:
previousValue = newValue;
} else {
// Invalid input; reset field value:
event.target.value = previousValue;
}
}
document.getElementById('myInput').onkeyup = validateInput;
}());
Working demo: http://jsfiddle.net/8kUdG/
It's worth noting that this will also validate empty strings, as well as unfinished numbers, like 5, or 42. (otherwise the user would have to insert the decimal sign after typing the decimals, which would be... weird).
And finally, keep in mind that this might not be a cross-browser safe solution. If you need a pure-JavaScript solution, you will need to refine it (i.e., this might not work in IE).
Edit: of course, showing an error message instead of resetting the input field to the previous value is also perfectly possible (updated JSFiddle):
(function() {
var pattern = /^(?=.)\d*(?:[.,]\d+)?$/;
var error = document.getElementById('error');
document.getElementById('myInput').onkeyup = function(event) {
event = event || window.event;
var newValue = event.target.value || '';
if (newValue.match(pattern)) {
error.innerHTML = '';
} else {
error.innerHTML = 'Not a valid number!';
}
};
}());
I leave it up to you to replace the alert with something more user-friendly.
The easiest solution would be something like this
// Returns true on valid, false on invalid
function myInputFilter(input)
{
var value = input.value;
var regex = /^[\d\,\.]*$/;
if(!regex.test(value))
return false;
return true;
}
You could edit the function to just take a string argument, but I've chosen to have it accept the text input element instead. The RegEx can be replaced by anything, I've made a simple one for this example. I would refine it a bit if I were you (You can use the excellent online tool RegExr)
Here is an example of the filter implemented
http://jsfiddle.net/kVV77/
You can use following regular expression:
/^[+-]?(?=.)(?:\d+,)*\d*(?:\.\d+)?$/
to allow only any number of comma and only one dot . with the condition that number cannot start with a comma. Number can have optional + or - at the start.