I am writing some Javascript/Jquery for a co-worker that is supposed to edit text in a textfield as the user is typing. The purpose of the code is to add formatting to a string of characters (in particular, formatting strings of twelve characters into a valid formatted mac address), however on Firefox I am unable to use the backspace to delete characters once they have been entered into the textfield.
Here is the code that does the formatting:
$(document).ready(function () {
var length = 0;
$("#mac_input").focusin(function (evt) {
$(this).keypress(function () {
content = $(this).val();
content_pre_format = content.replace(/\:/g, '');
content_formatted = content_pre_format.replace(/\n/g, '');
var text_input = $('#mac_input');
if (content_formatted.length % 12 == 0 && length != 0) {
text_input.val(text_input.val() + "\n");
}
length = content_formatted.length % 12;
if (length % 2 == 0 && length != 0) {
if (text_input.val().charAt(text_input.val().length - 1) == ':') {
} else {
text_input.val(text_input.val() + ':');
}
}
});
});
});
Edit: I figured out more about the bug. When I start typing, lets say "abc", right when I type the "c" the script edits the field to show "ab:c". I can backspace the "c" and the ":" but no more. At this point the text field shows "ab", however if I use ctrl-a to select all, the text field changes to "ab:"
here's a more robust solution (current solution will break if a user starts deleting anywhere except the end of the stirng):
$(document).ready(function() {
$("#mac_input").keydown(function (event) {
if (!((event.which > 47 && event.which < 71) || (event.which > 95 && event.which < 106))) {
event.preventDefault();
}
});
$("#mac_input").keyup(function () {
var content=$(this).val();
content = content.replace(/\:/g, '');
content = content.replace(/\n/g, '');
content = content.replace(/(\w{12}(?!$))/g, '$1\n').replace(/(\w{2}(?!\n)(?!$))/g, '$1:')
$(this).val(content);
});
});
it ensures the string is always parsed as a collection of MAC addresses
to explain, it uses to regular expressions,
([abcdef0123456789]{12}(?!$)) matches any sequence of twelve characters that can conform a MAC address and aren't at the end of the string (that's what the (?!$)) lookahead does), and replaces it with the matched string and an appended newline, then it matches any sequence of 2 MAC address characters (([abcdef0123456789]{2}) that aren't immediately followed by a new line or the end of the string ((?!\n)(?!$)).
Just check this: if(event.key == "Backspace") {return;} at the beginning of your keypress handler, and you should be fine.
NB: You have to add the event argument to your keypress handler function.
Related
I want to replace words with others as soon as you finish typing them like Facebook emoticons. I ran into a few problems though.
var word = 0;
var matches = ['dumb','sucker','idiot'];
document.addEventListener('input', function(e) {
if (e.target && e.target.id == 'myinput') {
if (e.data == ':' && word === 0) {
word = ':';
}
if (e.data != ':' && word != 0) {
word += e.data;
}
if (e.data == ':' && word.length > 1) {
var findit = word.replaceAll(':', '');
if (matches.indexOf(findit) != -1) {
var selection = window.getSelection();
myinput.innerHTML = myinput.innerHTML.replace(word + ':', 'something');
selection.modify('move', 'forward', 'lineboundary');
}
word = 0;
}
}
});
<div id="myinput" contenteditable="true"></div>
as you type a word that begins and ends with : it gets replaced at once. Problem is some times you may mistype the word after you have typed the first : and before typing the second one and once you do that you have to delete the whole word and start over instead of just deleting the part that is wrong and complete the word. How can I address that?
Second problem is once you replace the inner html the cursor moves back to the initial position instead of staying where you last typed. I addressed that with selection.modify('move', 'forward', 'lineboundary') but the issue comes when you try to correct something in the middle of the sentence or so because the cursor will now move to the end of it. How can I fix that?
I have a credit card field that I want to handle while the user inputs its credit card number.
Assumptions are that the user can enter digits and alphabetic characters, and a space must be added every four characters.
The input part works fine, but I have problems with backspace. Deleting with the backspace key works if I the cursor is on a digits, but it does not work fine when the cursor is on a space: in this case the user must hold backspace to properly delete some input.
An additional requirement is to let clipboard actions (copy, cut, paste) work properly on that field.
I cannot use any plugin for the solution (like the JQuery Mask Plugin), and I won't use keyCode directly, if possible.
Updated
JS Fiddle: https://jsfiddle.net/ot2t9zr4/10/
Snippet
$('#credit-card').on('keypress change blur', function () {
$(this).val(function (index, value) {
return value.replace(/[^a-z0-9]+/gi, '').replace(/(.{4})/g, '$1 ');
});
});
$('#credit-card').on('copy cut paste', function () {
setTimeout(function () {
$('#credit-card').trigger("change");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
<form class="" action="" method="post">
<fieldset>
<legend>Payment</legend>
<div class="beautiful-field field-group credit-cart">
<label class="label" for="credit-card">Credit card</label>
<input class="field" id="credit-card" value="" autocomplete="off" type="text" />
</div>
</fieldset>
</form>
</div>
Bind keypress event only and see.
$('#credit-card').on('keypress change', function () {
$(this).val(function (index, value) {
return value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ');
});
});
Check here.
Steve Davies already pointed it out, but if you only reformat the whole value with replace(), the caret position will always go at the end of the input value which can be annoying if the user edits what he previously entered. It will lead to a bad user experience if the caret position is elsewhere or a selection has been made in order to replace it with a new digit.
That being said, a good way to get rid of that behavior is to create a custom replace function with a for loop that goes through each character, then you will be able to know if the space inserted is before the current caret position and update the position if it's the case.
Pure javascript solution: https://jsfiddle.net/pmrotule/217u7fru/.
EDIT: I added support for the American Express format (15 digits instead of 16).
input_credit_card = function(jQinp)
{
var format_and_pos = function(input, char, backspace)
{
var start = 0;
var end = 0;
var pos = 0;
var value = input.value;
if (char !== false)
{
start = input.selectionStart;
end = input.selectionEnd;
if (backspace && start > 0) // handle backspace onkeydown
{
start--;
if (value[start] == " ")
{ start--; }
}
// To be able to replace the selection if there is one
value = value.substring(0, start) + char + value.substring(end);
pos = start + char.length; // caret position
}
var d = 0; // digit count
var dd = 0; // total
var gi = 0; // group index
var newV = "";
var groups = /^\D*3[47]/.test(value) ? // check for American Express
[4, 6, 5] : [4, 4, 4, 4];
for (var i = 0; i < value.length; i++)
{
if (/\D/.test(value[i]))
{
if (start > i)
{ pos--; }
}
else
{
if (d === groups[gi])
{
newV += " ";
d = 0;
gi++;
if (start >= i)
{ pos++; }
}
newV += value[i];
d++;
dd++;
}
if (d === groups[gi] && groups.length === gi + 1) // max length
{ break; }
}
input.value = newV;
if (char !== false)
{ input.setSelectionRange(pos, pos); }
};
jQinp.keypress(function(e)
{
var code = e.charCode || e.keyCode || e.which;
// Check for tab and arrow keys (needed in Firefox)
if (code !== 9 && (code < 37 || code > 40) &&
// and CTRL+C / CTRL+V
!(e.ctrlKey && (code === 99 || code === 118)))
{
e.preventDefault();
var char = String.fromCharCode(code);
// if the character is non-digit
// -> return false (the character is not inserted)
if (/\D/.test(char))
{ return false; }
format_and_pos(this, char);
}
}).
keydown(function(e) // backspace doesn't fire the keypress event
{
if (e.keyCode === 8 || e.keyCode === 46) // backspace or delete
{
e.preventDefault();
format_and_pos(this, '', this.selectionStart === this.selectionEnd);
}
}).
on('paste', function()
{
// A timeout is needed to get the new value pasted
setTimeout(function()
{ format_and_pos(jQinp[0], ''); }, 50);
}).
blur(function() // reformat onblur just in case (optional)
{
format_and_pos(this, false);
});
};
input_credit_card($('#credit-card'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
<form class="" action="" method="post">
<fieldset>
<legend>Payment</legend>
<div class="beautiful-field field-group credit-cart">
<label class="label" for="credit-card">Credit card</label>
<input class="field" id="credit-card" value="" autocomplete="off" type="text" />
</div>
</fieldset>
</form>
</div>
Since I cannot just reply to Developer107's comment; If you only want digits (with regex and don't want to specify it on the field. You can do it like this:
$('#credit-card').on('keypress change', function () {
$(this).val(function (index, value) {
return value.replace(/[^0-9]/g, "").replace(/\W/gi, '').replace(/(.{4})/g, '$1 ');
});
});
https://jsfiddle.net/ot2t9zr4/4/
I wanted to share my solution, in case someone is still struggling to achieve the desired affect.
My code is a refined version of #tonybrasunas's answer. It will add spaces every 4 characters, filter out non-numerical characters, fix character position, backspace, and only move the cursor forward if the character is valid, but still allow pushing with valid characters.
// FORMAT CC FIELD
//
$('#credit-card').on('input', function () {
$(this).val(function (index, value) {
// Store cursor position
let cursor = $(this).get(0).selectionStart;
// Filter characters and shorten CC (expanded for later use)
const filterSpace = value.replace(/\s+/g, '');
const filtered = filterSpace.replace(/[^0-9]/g, '');
const cardNum = filtered.substr(0, 16);
// Handle alternate segment length for American Express
const partitions = cardNum.startsWith('34') || cardNum.startsWith('37') ? [4,6,5] : [4,4,4,4];
// Loop through the validated partition, pushing each segment into cardNumUpdated
const cardNumUpdated = [];
let position = 0;
partitions.forEach(expandCard => {
const segment = cardNum.substr(position, expandCard);
if (segment) cardNumUpdated.push(segment);
position += expandCard;
});
// Combine segment array with spaces
const cardNumFormatted = cardNumUpdated.join(' ');
// Handle cursor position if user edits the number later
if (cursor < cardNumFormatted.length - 1) {
// Determine if the new value entered was valid, and set cursor progression
cursor = filterSpace !== filtered ? cursor - 1 : cursor;
setTimeout(() => {
$(this).get(0).setSelectionRange(cursor, cursor, 'none');
});
}
return cardNumFormatted;
})
});
//
// END OF FORMAT CC FIELD
An Answer for 2021: Handling Backspace, Cursor Position, and American Express correctly
To handle Backspace and cursor arrows, we have to store the original cursor position and restore it with a setTimeout() when editing a spot anywhere other than the end of the string.
For American Express, we set up partitions to handle the 4-6-5 spacing format for Amex and the 4-4-4-4 spacing for all other cards. And we loop through them to add spaces.
$('#credit-card').on('keyup', function () {
$(this).val(function (index, value) {
const selectionStart = $(this).get(0).selectionStart;
let trimmedCardNum = value.replace(/\s+/g, '');
if (trimmedCardNum.length > 16) {
trimmedCardNum = trimmedCardNum.substr(0, 16);
}
/* Handle American Express 4-6-5 spacing format */
const partitions = trimmedCardNum.startsWith('34') || trimmedCardNum.startsWith('37')
? [4,6,5]
: [4,4,4,4];
const numbers = [];
let position = 0;
partitions.forEach(partition => {
const part = trimmedCardNum.substr(position, partition);
if (part) numbers.push(part);
position += partition;
});
const formattedCardNum = numbers.join(' ');
/* Handle caret position if user edits the number later */
if (selectionStart < formattedCardNum.length - 1) {
setTimeout(() => {
$(this).get(0).setSelectionRange(selectionStart, selectionStart, 'none');
});
};
return formattedCardNum;
})
});
If you have a routine of your own to detect American Express numbers, use it. This simply examines the first two digits and compares to PAN/IIN standards.
I also posted an answer on how to do this in an Angular application.
I solved this in Vue JS by creating a custom on-change handler. Rather than show it here, I will provide a link to that solution: Javascript: Set cursor position when changing the value of input
Based on my research, it is required to manage the position of the cursor yourself if you wish to fully-support editing with good UX.
pmrotule's vanilla JavaScript solution is great, but mine is drastically simpler, so it could be worthwhile to examine.
function cc_format(value) {
var v = value.replace(/\s+/g, '').replace(/[^0-9]/gi, '')
var matches = v.match(/\d{4,16}/g);
var match = matches && matches[0] || ''
var parts = []
for (i=0, len=match.length; i<len; i+=4) {
parts.push(match.substring(i, i+4))
}
if (parts.length) {
return parts.join(' ')
} else {
return value
}
}
Use
$('#input-cc-number').on('keyup',function() {
var cc_number = cc_format($(this).val());
$('#input-cc-number').val(cc_number);
});
Your issue at its core is that when an input field's value is updated using JavaScript, the cursor/selection position is set to the end of the string.
When user-input is appending to the end, this is fine, but if deleting, or inserting digits in the middle, this becomes quite annoying as you have observed. One way to deal with this would be to save and restore the cursor position within the field before and after each edit.
Crudely done:
$('#credit-card').on('keyup keypress change', function () {
var s = this.selectionStart, e = this.selectionEnd;
var oldleft = $(this).val().substr(0,s).replace(/[^ ]/g, '').length;
$(this).val(function (index, value) {
return value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ');
});
var newleft = $(this).val().substr(0,s).replace(/[^ ]/g, '').length;
s += newleft - oldleft;
e += newleft - oldleft;
this.setSelectionRange(s, e);
});
This is not a full solution as the s and e positions will need updating if your code inserts/removes characters that result in these locations being moved.
You could also significantly optimise this by not setting val() if no update is required.
$('.credit-card').keyup(function (e) {
if (e.keyCode != 8) {
if ($(this).val().length == 4) {
$(this).val($(this).val() + " ");
} else if ($(this).val().length == 9) {
$(this).val($(this).val() + " ");
} else if ($(this).val().length == 14) {
$(this).val($(this).val() + " ");
}
}
});
This should work fine its just for card with format 4444 5555 2222 1111 and back space works correctly
To me #pmrotule answer was the best answer so far in this post. Good credit card spacing apparently helps conversion rate in shopping carts according to extensive research produced by Stripe.
Additionally however, setting the "type" attribute of the html input field to "tel" is also important, as well as inputmode="numeric" as well as setting the auto complete type cc-number, all also help improve checkout conversion rate. Especially on mobile when the user gets a numeric keyboard instead of qwerty.
Unfortunately this breaks #pmrotule's code. On another SO post I found out about Cleave.js which is a well tested library for this purpose & plays nicely with the tel input type: https://github.com/nosir/cleave.js
Putting it all together:
<input class="field" id="number" type="tel" inputmode="numeric" autocomplete="cc-number" />
with JS:
var cleave = new Cleave('#number', {
creditCard: true,
onCreditCardTypeChanged: function (type) {
console.log('The detected card type is: '+type);
}
});
My Requirement is to validate the ip ranges, I need to create a JavaScript function to accept only numeric and it must allow only between the range 0 to 255. If anything is entered beyond that it must alert a message.
I am currently using this below function
<script language="JavaScript">
function allownums(a)
{
if(a <48 ||a > 57)
alert("invalid")
else
alert("vaild")
}
</script>
<input type='text' id='numonly' onkeypress='allownums(event.keycode)'>
I am new to JavaScript, Need some experts suggestion to fix my requirement. Please suggest me
Thanks
Sudhir
Currently you have the test
(a < 48) || (a > 57)
for invalid values. So I would change those:
(a < 0 ) || (a > 255)
You may also need to consider what you'll do with non-integral input like 2.3 - either round it or treat it as invalid.
At present, as Kelvin Mackay points out, you are performing the validation on the keypress event rather than the input value, so change the onkeypress to allownums(this.value).
I would advise changing the alert to a warning in a div, and using the validation to enable/disable a submit button, as popups are quite annoying in just about every circumstance.
To clear the input when an invalid entry is made (as requested in a comment) would make it rather annoying for the user; as soon as a key is pressed to add a digit and make the input invalid, the whole input is cleared. The code, however, would be:
if(!validnum(this.value))
this.value="";
in the input tag, thus:
<input type='text' id='numonly'
onkeyup='if(!validnum(this.value)) this.value="";'>
with the function changed to:
function validnum(a) {
if(a < 0 || a > 255)
return false;
else
return true;
}
or more succinctly:
function validnum(a) {
return ((a >= 0) && (a <= 255));
}
Edit: To alert and clear the box, if you must:
function validOrPunchTheUser(inputElement) {
if(!validnum(inputElement.value)) {
window.alert('badness'); // punch the user
inputElement.value = ""; // take away their things
}
}
<input type='text' id='numonly'
onkeyup='validOrPunchTheUser(this)'>
However, reading other answers, apparently you are looking to validate an octet (e.g. in an IP address). If so, please state that in the question, as it passed me by today. For an octet:
function validateIPKeyPress(event) {
var key = event.keyCode;
var currentvalue = event.target.value;
if(key < 96 || key > 105)
{
event.preventDefault();
window.alert('pain');
return false;
}
else if(currentvalue.length > 2 ||
(currentvalue.length == 2 &&
key > 101)) {
window.alert('of death');
event.preventDefault();
event.target.value = event.target.value.substring(0,2);
}
else
return true;
}
With the input tag:
<input type='text' id='octet'
onkeydown='validateIPKeyPress(event)'>
Except please don't use alerts. If you take out the alert lines, it will silently prevent invalid inputs. Note the change to use onkeydown now, so that we can catch invalid key presses and prevent the value changing at all. If you must clear the input, then do if(!validateIPKeyPress(event)) this.value = "";.
I would rather go instantly for validation of whole ip address. Allowing input both numbers and dots, parsing them thru REGEX pattern.
Pattern usage example you could fetch here:
http://www.darian-brown.com/validate-ip-addresses-javascript-and-php-example/
The code itself would look something like:
<input type='text' id='numonly' value="" onkeypress='allowIp(event)' onkeyup='javascript:checkIp()'>
function allowIp(e){
if((e.keyCode < 48 || e.keyCode > 57) && e.keyCode != 46) // both nubmer range and period allowed, otherwise prevent.
{
e.preventDefault();
}
}
function checkIp()
{
var ip = $("#numonly").val();
/* The regular expression pattern */
var pattern = new RegExp("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
/* use javascript's test() function to execute the regular expression and then store the result - which is either true or false */
var bValidIP = pattern.test(ip);
if(bValidIP){
// IP has ok pattern
$("#numonly").css("background", "green");
}
else {
$("#numonly").css("background", "red");
}
}
You could check it here on fiddle
http://jsfiddle.net/Indias/P3Uwg/
Single Integer
You can use the following solution to check if the user input for a single integer is between 0 - 255:
document.getElementById('example').addEventListener('input', event => {
const input = event.target.value;
console.log(/^\d+$/.test(input) && input > -1 && input < 256);
});
<input id="example" type="text" placeholder="Enter single integer" />
IP Address
Alternatively, you can use the code below to verify that each section of an IP address is between 0 - 255:
document.getElementById('example').addEventListener('input', event => {
const input = event.target.value;
console.log(input === new Uint8ClampedArray(input.split('.')).join('.'));
});
<input id="example" type="text" placeholder="Enter IP address" />
You need to validate the current value of the input, rather than the last key that was pressed:
<input type='text' id='numonly' onkeypress='allownums(this.value)'>
Your function then just needs to be modified to: if(a < 0 || a > 255)
A function like this should do it:
function allownums(value){
var num = parseInt(value,10);
if(num <0 || num>255)
alert('invalid')
}
Then have your html look like:
<input type='text' id='numonly' onblur='allownums(this.value)'>
Live example: http://jsfiddle.net/USL3E/
Update
I've set up a fiddle that does some basic IP-formatting and checks weather or not all input is in range (0 - 255) etc... feel free to use it, improve it, study it... I've also updated the code snippet here to match the fiddle
There are several things you're not taking into account. First and foremost is that not all browsers have a keycode property set on the event objects. You're better off passing the entire event object to the function, and deal with X-browser issues there. Secondly, you're checking key after key, but at no point are you checking the actual value that your input field is getting. There are a few more things, like the use of the onkeypress html attribute (which I don't really like to see used), and the undefined return value, but that would take us a little too far... here's what I suggest - HTML:
<input type='text' id='numonly' onkeypress='allowNums(event)'>
JS:
function allowNums(e)
{
var key = e.keycode || e.which;//X-browser
var allow = '.0123456789';//string the allowed chars:
var matches,element = e.target || e.srcElement;
if (String.fromCharCode(key).length === 0)
{
return e;
}
if (allow.indexOf(String.fromCharCode(key)) === 0)
{//dot
element.value = element.value.replace(/[0-9]+$/,function(group)
{
return ('000' + group).substr(-3);
});
return e;
}
if (allow.indexOf(String.fromCharCode(key)) > -1)
{
matches = (element.value.replace(/\./g) + String.fromCharCode(key)).match(/[0-9]{1,3}/g);
if (+(matches[matches.length -1]) <= 255)
{
element.value = matches.join('.');
}
}
e.returnValue = false;
e.cancelBubble = true;
if (e.preventDefault)
{
e.preventDefault();
e.stopPropagation();
}
}
Now this code still needs a lot of work, this is just to get you going, and hopefully encourage you to look into the event object, how JS event handlers work and all the rest. BTW, since you're new to JS, this site is worth a bookmark
function fun_key()
{
var key=event.keyCode;
if(key>=48 && key<=57)
{
return true;
}
else
{
return false;
alert("please enter only number");
}
}
and you can call this function on keypress event like:
<asp:textbox id="txtphonenumber" runat="server" onkeypress="return fun_key()"> </asp"textbox>
I've seen many answers that have overlooked two important factors that may fail to validate range number on keypress:
When the value in input textbox is NOT SELECTED, the real outcome should be (input.value * 10) + parseInt(e.key) and not simply input.value + parseInt(e.key). It should be * 10 because you add one more digit at the back during keypress, e.g. 10 becomes 109.
When the value in input textbox IS SELECTED, you can simply check if Number.isInteger(parseInt(e.key)) because when 255 is selected, pressing 9 will not turn into 2559 but 9 instead.
So first of all, write a simple function that check if the input value is selected by the user:
function isTextSelected (input) {
if (!input instanceof HTMLInputElement) {
throw new Error("Invalid argument type: 'input'. Object type must be HTMLInputElement.");
};
return document.getSelection().toString() != "" && input === document.activeElement;
}
Next, this will be your on keypress event handler that takes into consideration of the above two factors:
$("input[type='number']").on("keypress", function (e) {
if (!Number.isInteger(parseInt(e.key)) || (($(this).val() * 10) + parseInt(e.key) > 255
&& !isTextSelected($(this)[0]))) {
e.preventDefault();
};
});
Take note of this condition within another brackets, it is one whole condition by itself:
(($(this).val() * 10) + parseInt(e.key) > 255 && !isTextSelected($(this)[0]))
For the < 0 condition, you don't even need it here because the negative sign (-) will be automatically prevented as the sign itself is not an integer.
KNOWN ISSUE: The above solution, however, does not solve the situation when the user move the cursor to the start position of 29 and press 1, which will become 129. This is because 29 * 10 = 290, which already exceed 255, preventing user from entering 129, which is valid. The start position is particularly hard to track when the input type="number". But it should be enough to resolve the normal way of input for an integer range field. Any other better solutions are welcome.
I created this fiddle that the div value changes based on your dropdown list selection. http://jsfiddle.net/qSkZW/20/
I want to take it one step further and this is to create a textbox field that if you add for example the number 2 it will change the div value to 240 (in real the 120 you find in the script it will be a php var). If it writes 3 then to 360.
Additionally there must be two limitations.
Prevent them from using non-numeric characters.
The maximum number is pre-configured (from a php variable). Like if the max value is set to 10, if the user writes 30 it will return to 10.
Thank you for your help.
Okay, so first, create a textfield (example id="textfield"), then modify your listener's action to
$("#quantity").change(function () {
var price = parseInt($(this).val(), 10)*120
$("#textfield").attr('value="'+price+'"');
# sets the default value of #textfield to the selection from #quantity
})
.change()
$("#textfield").blur(function () {
# when the element looses focus (they click/tab somewhere else)
var valid = /^\d{2}$/;
# this means any 2 numbers. change {2} to {3} or however many digits.
# you can also also use d[0-10] to identify a range of numbers.
if ( $(this).text() != valid ) {
$("#message").text("Only numbers please!");
$("#message").fadeIn();
# add <span id="message" style="display:none;"></span> next to #textfield
# enclose #textfield & #message in the same element (like <li> or <div>)
}
else {
$("#message").fadeOut();
}
});
Could you please provide more info about #2 (I don't have a clear understanding of what is supposed to happen)
Quick question: why are you trying to put a price in an editable element?
This will do it: http://jsfiddle.net/ebiewener/pBeM8/
You bind the keydown event to the input box in order to prevent the undesired characters from being entered, and bind the keyup event in order check the value & modify the div's height.
$('input').keydown(function(e){
if(!(e.which >= 48 && e.which <=58) && e.which !== 8 && e.which !== 46 && e.which !== 37 && e.which !== 39){ //prevent anything other than numeric characters, backspace, delete, and left & right arrows
return false;
}
})
.keyup(function(){
val = $(this).val();
if(val > 10){
val = 10;
$(this).val(10);
}
$('div').height(val * 10);
});
var max = 30;
$('input').keyup(function() {
var v = $(this).val();
v = isNaN(v)?'':v;
v = v > max ? max : v;
$(this).val(v);
$('div').html(v * 120);
});
http://jsfiddle.net/vWf2x/2/
Assuming the cursor position in a tinymce editor is inside a paragraph.
When a user hits backspace i need to know which character will get deleted.
It is necessary to know this before the character gets removed (onKeyDown is ok, onKeyUp is too late).
How can i find out which character gets deleted on backspace (before it actually gets deleted)?
The code above doesn't take into account backspacing in the middle of a paragraph, or backspacing a whole selection. Try something like the a-tools plugin (although there are several others like it) in combination with the following event handler:
jQuery('input, textarea').keydown(function(e) {
if(e.keyCode === 8) {
var selection = jQuery(this).getSelection();
var selStart = (selection.length) ? selection.start : selection.start - 1;
var selEnd = selection.end;
alert(jQuery(this).val().slice(selStart, selEnd));
}
});
in one of my plugins i set onKeyDown
ed.onKeyDown.add(function(ed, evt) {
if (paragraph && evt.keyCode == 8 && ed.selection.isCollapsed()) {
//insert special marker char
var value = '<span id="__ircaret" class="ircaret">\u2060</span>';
ed.selection.setContent(value, {format : 'raw', no_events: 1});
// node is the dom node the caret is placed in
var node = ed.selection.getNode();
var node_content = $(node).text();
var position = node_content.search('\u2060');
// this is the character
var char_vor_cursor = position != 0 ? node_content.slice(position - 1, position) : '';
// Test for soft-hyphen
if (char_vor_cursor != '' && char_vor_cursor.charCodeAt(0) == 173) {
// correct innerHTML
var text_after_backspace = node_content.slice(0, position - 1) + '<span id="__ircaret" class="ircaret">\u2060</span>' + node_content.slice(position + 1);
node.innerHTML = text_after_backspace;
}
var caret_node = $(node).find('#__ircaret').get(0);
// select caretnode and remove
ed.selection.select(caret_node);
$(ed.getBody()).find('.ircaret').remove();
}
}