I have created within knockoutJS a computed observable that supports user input as well as performs text manipulation on the input.
This observable is bound to input field and label. The intent is to allow a user to enter a new name but I want to prevent the user from using non-alphanumeric characters. The function works both in bindings and evaluation of the string, but the replace function does not seem to update. The substring function works (limiting the text to 255 characters) but I think I have something not set exactly right in the replace. Int eh current funciton, if an illegal character is entered the user receives the toastr alert but the replace function does not replace the character with white space. I'd appreciate any suggestions.
html
<label class="reportNameTextBox" title="Click to edit report name" data-bind="text: NameFormatted() == null || NameFormatted().trim().length == 0 ? '[ Click To Enter Name ]' : NameFormatted(), css: { 'noData': NameFormatted() == null || NameFormatted().trim().length == 0 }"></label>
<input class="editInput" type="text" data-bind="value: NameFormatted" />
knockout
report.NameFormatted = ko.computed({
read: function () {
return report.Name().substring(0, 255);
},
write: function (value) {
var insertedText = value;
var Exp = /^[a-zA-Z0-9]*$/i;
if (!insertedText.match(Exp)) {
DisplayWarning('Attention', 'Non-alphanumeric may not be used.');
return report.Name(insertedText.substring(0, 255)).replace(/[^a-zA-Z 0-9]+/g, ''); ;
}
else {
DisplayWarning('Success', 'yeah');
return report.Name(insertedText.substring(0, 255));
}
},
owner: this
});
I believe your problem lies on this line:
return report.Name(insertedText.substring(0, 255)).replace(/[^a-zA-Z 0-9]+/g, '');
You're chaining the replace method to the wrong object (report.Name instead of substring)
return report.Name(insertedText.substring(0, 255).replace(/[^a-zA-Z 0-9]+/g, ''));
Just move the replace method inside the bracket and it should work as expected.
Related
I want to validate an input in real time way.
The input has type text and must validate only an input having : number(s) and/or floating point or comma.
Also the input accepts only two numbers after the floating point/comma.
Examples :
- 12.23 Valid
- 12,23 Valid
- 12.2 Valid
- 12,02 Valid
- 2 Valid
- 12.035 Invalid
- 12.36E Invalid
- test Invalid
I suggest tracking the live input validation with a /^(\d*)([,.]\d{0,2})?$/ regex that allows typing any 0 or more digits at the start, and then an optional substring of , or . and then 0, 1 or 2 digits. If there is a match, re-format the value by replacing , with .. If there input value is not matched, replace it with the last good value (say, introduce a variable called prevValue for that).
Once you want to submit this value, you need to make sure the value is in the final format, that is, there should be no . at the end. To enable this, add a pattern attribute to your <input> and assign the ^\d+(?:\.\d{1,2})?$ regex to it. Here, it will already require 1+ digits at the start of the string, and then will match an optional substring of a . followed with 1 or 2 digits. See the regex demo. Since the comma will get replaced with a dot, you need no [.,] pattern, \. is enough.
Also, it is a good idea to handle the input value change on paste.
var prevValue = "";
var patt = /^(\d*)([,.]\d{0,2})?$/;
function validateCurrencyPattern(price){
var matchedString = price.match(patt);
if (matchedString) {
prevValue = matchedString[1] + (matchedString[2] ? matchedString[2].replace(",", ".") : "")
return prevValue;
}
else {
return prevValue;
}
}
$(document).on("keypress keyup blur paste","#field", function (event) {
$(this).val(validateCurrencyPattern($(this).val()));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<input type="text" id="field" name="field" pattern="^\d+(?:\.\d{1,2})?$"/>
<input type="Submit"/>
</form>
Since I did not find the solution on stack and spent some hours to develop a solution that can help others i'll share what i've done :
I used the RegExp pattern to validate the number.but i can't do it with one pattern so i've created two patterns.
The first validates: x*.yy
And the second validates: x*,yy
Constraints : isNumeric doesn't accept float with comma.so that's why i've converted it.
The function validation function code :
and The call for function mixing the events (keypress keyup blur)
function validateCurrencyPattern(price){
var patt = new RegExp(/[0-9]+[.]{1}[0-9]{2}/i);
var convertedPrice =price.replace(',', '.');
var matchedString = price.match(patt) ;
var matchedString2 = convertedPrice.match(patt) ;
if (matchedString) {
return matchedString
}
if (matchedString2) {
return matchedString2
}
if((!$.isNumeric(convertedPrice))|| convertedPrice<0){
return null;
}
else if(!matchedString && !matchedString2){
return convertedPrice;
}
}
$(document).on("keypress keyup blur","#field", function (event) {
$(this).val(validateCurrencyPattern($(this).val()));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="field" name="field">
Feel Free to optimize this solution or suggest another alternative that may be better than the existing solution.
I have a regex for a set of use cases
Based on that regex I'm trying to prevent the user to type invalid formats.
The regex works and preventing the user adding invalid formats also works.
The part with which I'm struggling now is that if the default value is invalid, the user cannot add additional valid characters.
Here is what I have: http://jsfiddle.net/jgqco7by/2/.
<input id="myInput" type="text" value="co vi1d-" />
var previousValue = document.getElementById('myInput').value;
var pattern = /^[a-zA-Z]+(?:[ -][a-zA-Z]+)*([ ]|[-])?$/g;
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').oninput = validateInput;
In this example since I have a default value which contains a number, which is not allowed, everything I type is replaced with previous value because the regex keeps coming back as invalid.
How could I build this so that, if the default value is invalid, the user can still add additional VALID values without having to remove the default invalid values first?
If you want to have the invalid data and a valid one in the same input I'm not seeing how it will happened with your approach.
If you want to have an initial value (that can be either valid or invalid) and then to append something (which is valid) then why are you checking for the initial state.
The third variant is to have both
Empty field and putting a valid chars only
Initial value (valid or invalid) and appending something (valid)
And the result will be to have a valid stuff.
Please place your question / requirement in a more structured manner.
As for the code I would suggest to change your regex. I can give suggestions for modification. :)
For the code:
<input id="myInput" type="text" value="co vi1d-" />
<p id="messageField"></p>
(function() {
const pattern = new RegExp(/^[a-zA-Z]+(?:[ -][a-zA-Z]+)*([ ]|[-])?$/g);
const messageField = document.getElementById('messageField');
function validateInput(event) {
var newValue = event.target.value; // no sense to have a check and to overwrite with window.event , its a different context
messageField.innerText = pattern.test(newValue) ? '' : 'incorrect input'; // its better to use test() method rather than match()
}
document.getElementById('myInput').oninput = validateInput;
}());
I wanted to know which character the user is typing into an input:
I have an input:
<input maxlength="20"/>
and a script that returns the last typed char:
var eingabe;
$('form').on('keypress', function(event) {
/// if no whitespace:
if (String.fromCharCode(event.keyCode).replace(/\s/g, "").length > 0) {
eingabe = String.fromCharCode(event.keyCode);
$('#eingabe').html("<div>Eingabe : "+ eingabe +"</div>");
}
});
My question is:
because my input has a maxlength attribute, the last typed character on the keyboard is sometimes not the last -real- typed character into the input because the input is "full". How can I get the last character typed into the input?
I haven't tried it, but it must work...
Set onkeypress= or onkeydown= on the Input element and store the key value in a LastChr variable.
I had a similar problem. I wanted to call a function if the user types a specific character into my input field. I solved it with the following:
var input = document.getElementById('myInput');
input.addEventListener('input', function() {
// Get cursor position
var start = this.selectionStart;
// Get last typed character
var lastChar = String.fromCharCode(this.value.charCodeAt(start - 1));
if(lastChar === '[YOURCHARHERE]') {
// do something
}
});
Please keep in mind, that 'input' is only supported down to IE8, but if you don't care about a proprietary browser, you should be fine. I hope this helps.
Inside your function, use the value of the input element to get the last character like $('#input_field').val().substr($('#input_field').val().length - 1) or use your best coding skill to accomplish something similar without accessing the field twice, wink wink.
Use keyup instead:
$('form').on('keyup', function(event) {
var cursorPos = event.target.selectionStart;
var lastTypedChar = elem.target.value[cursorPos - 1];
});
I'm new to KnockoutJS. I know how to define an observable that will be used to change the text of an element (or be updated from a text element), however, I want the data in my model to be actually a regular expression with read/write access. I want to set it using a textarea like:
<textarea data-bind="value: regex"></textarea>
And show it on the page using:
<span data-bind="text: regex"></span>
Now the initialization is working:
//inside the model
this.regex = ko.observable( /,/g );
And both the textarea and span get updated (because the native regular expression variable has a toString() function that works perfectly well showing a string representation of the regular expression). But when I change the regex in the textarea the span doesn't update. It seems like setting the observable is failing.
This is understandable because the value from textarea is just a text and in order to convert it to an actual regular expression, some code is needed. I have the code. Let's call it function str2regex() with a body similar to this:
//this is pseudo code and doesn't neccesarily work
function str2regex( str )
var r = str.match( "^\/(.+?)\/([mig])*$" );
if ( r ) {
if ( r[2] === null ) {
return new RegExp( r[1] );
} else {
return new RegExp( r[1], r[2] );
}
}
return null;
}
How can I set the value of type regular expression in my model using the text that is coming from the textarea?
You should transform your str2regex to computed observable like this:
// str2regex transformed to computed observable
self.regex = ko.computed(function(){
var m = self.regex_string().match(/^\/(.+)\/([mig])*$/);
return m ? new RegExp(m[1], m[2]) : null;
});
But you still should track your regex string editable in textarea (regex_string observable in my code).
Take a look: http://jsbin.com/ofehuj/2/edit
I am stuck in implementing the following:
User starts typing in a textbox.
The javascript on page captures the first character typed, validates that it is an english alphabet (a-z,A-Z) and converts it to lowercase (if necessary).
Make an XMLHttp request based on the input (i.e. if first input character is a, get a.xml, if b get b.xml and so on).
I know how to do the last part (make the xmlhttp request) but am kind of stuck on how to capture the first character and validate it (in a way that works on all browsers). Please guide. Thanks.
Clarification: This is to create a Google Suggest like autocomplete-drop-down menu without the need for server side programs.
Something like this should work:
HTML:
<input type="text" id="myField" />
And in JS:
window.onload = function() {
document.getElementById('myField').onkeyup = function() {
// Validate that the first letter is A-Za-z and capture it
var letter = this.value.match(/^([A-Za-z])/);
// If a letter was found
if(letter !== null) {
// Change it to lowercase and update the value
letter = letter[0].toLowerCase();
this.value = letter + this.value.substring(1);
// Do the request
}
}
}
My vanilla-JS skills are a bit rusty but this should do the trick. Just for the heck of it, here's the same using jQuery:
$(function() {
$('#myField').keyup(function() {
var letter = $(this).val().match(/^([A-Za-z])/);
// If a letter was found
if(letter !== null) {
// Change it to lowercase and update the value
letter = letter[0].toLowerCase();
$(this).val(letter + $(this).val().substring(1);
// Do the request
}
});
});
What part of the problem do you not know how to do? Here's an approach that you can follow. Very likely to need adjustments, but a good starting point
if our text field's id is 'txt'
document.getElementByID('txt').onkeypress = function(e) {
var textInField = this.value;
if (textInField.length == 1) {
var firstChar = textInField.charAt(0);
if (/[a-zA-Z]/.test(firstChar)) {
sendXHR(textInField.value.toLowerCase())
}
} else {
// What do you do if there is one or more chars???
}
}
Note that the other answers here mention onchange, that doesn't fire until the focus leaves the field, which I don't think is what you want