I am using the the following function in javascript.
function chknumber(a) {
a.value = a.value.replace(/[^0-9.]/g, '', '');
}
This function replaces any non numeric character entered in a textbox on whose onkeyup i have called the above function. The problem is it allows this string as well
1..1
I want the function to replace the second dot character as well. Any suggestions will be helpful.
I don't advocate simplistically modifying fields while people are trying to type in them, it's just too easy to interfere with what they're doing with simple handlers like this. (Validate afterward, or use a well-written, thoroughly-tested masking library.) When you change the value of a field when the user is typing in it, you mess up where the insertion point is, which is really frustrating to the user. But...
A second replace can correct .. and such:
function chknumber(a) {
a.value = a.value.replace(/[^0-9.]/g, '').replace(/\.{2,}/g, '.');
}
That replaces two or more . in a row with a single one. But, it would still allow 1.1.1, which you probably don't want. Sadly, JavaScript doesn't have lookbehinds, so we get into more logic:
function chknumber(a) {
var str = a.value.replace(/[^0-9.]/g, '').replace(/\.{2,}/g, '.');
var first, last;
while ((first = str.indexOf(".")) !== (last = str.lastIndexOf("."))) {
str = str.substring(0, last) + str.substring(last+1);
}
if (str !== a.value) {
a.value = str;
}
}
Can't guarantee there aren't other edge cases and such, and again, every time you assign a replacement to a.value, you're going to mess up the user's insertion point, which is surprisingly frustrating.
So, yeah: Validate afterward, or use a well-written, thoroughly-tested masking library. (I've had good luck with this jQuery plugin, if you're using jQuery.)
Side note: The second '' in your original replace is unnecessary; replace only uses two arguments.
try with match method if your input is "sajan12paul34.22" the match function will return a array contain [12 , 34.22]
the array index [0] is used for getting first numeric value (12)
function chknumber(a) {
a.value = a.value.match(/[0-9]*\.?[0-9]+/g)[0];
}
Related
I have this string made up for a TMS program... I later found out I want the program to NOT select these postalcodes, it's now matching the string. I want it to be able to select anything between 1000-10000\s*a-zA-Z except for this:
(8388|8389|8390|8391|8392|8393|8394|8395|8396|8397|8398|8400|8401|8403|8404|8405|8406|8407|8408|8409|8410|8411|8412|8413|8414|8415|8420|8421|8422|8423|8424|8425|8426|8427|8428|8430|8431|8432|8433|8434|8435|8440|8441|8442|8443|8444|8445|8446|8447|8448|8449|8451|8452|8453|8454|8455|8456|8457|8458|8459|8461|8462|8463|8464|8465|8466|8467|8468|8469|8470|8471|8472|8474|8475|8476|8477|8478|8479|8481|8482|8483|8484|8485|8486|8487|8488|8489|8490|8491|8493|8494|8495|8497|8500|8501|8502|8503|8505|8506|8507|8508|8511|8512|8513|8514|8515|8516|8517|8520|8521|8522|8523|8524|8525|8526|8527|8528|8529|8530|8531|8532|8534|8535|8536|8537|8538|8539|8541|8542|8550|8551|8552|8553|8554|8556|8560|8561|8563|8564|8565|8566|8567|8571|8572|8573|8574|8581|8582|8583|8584|8600|8601|8602|8603|8604|8605|8606|8607|8608|8611|8612|8613|8614|8615|8616|8617|8618|8620|8621|8622|8623|8624|8625|8626|8627|8628|8629|8631|8632|8633|8635|8636|8637|8641|8642|8644|8647|8650|8651|8658|8700|8701|8702|8710|8711|8713|8715|8721|8722|8723|8724|8730|8731|8732|8733|8734|8735|8736|8737|8741|8742|8743|8744|8745|8746|8747|8748|8749|8751|8752|8753|8754|8755|8756|8757|8758|8759|8761|8762|8763|8764|8765|8766|8771|8772|8773|8774|8775|8800|8801|8802|8804|8805|8806|8807|8808|8809|8811|8812|8813|8814|8816|8821|8822|8823|8830|8831|8832|8833|8834|8835|8841|8842|8843|8844|8845|8850|8851|8852|8853|8854|8855|8856|8857|8860|8861|8862|8871|8872|8880|8881|8882|8883|8884|8885|8890|8891|8892|8893|8894|8895|8896|8897|8899|8900|8901|8902|8903|8911|8912|8913|8914|8915|8916|8917|8918|8919|8921|8922|8923|8924|8925|8926|8927|8931|8932|8933|8934|8935|8936|8937|8938|8939|8941|9001|9003|9004|9005|9006|9007|9008|9009|9011|9012|9013|9014|9021|9022|9023|9024|9025|9026|9027|9031|9032|9033|9034|9035|9036|9037|9038|9040|9041|9043|9044|9045|9047|9050|9051|9053|9054|9055|9056|9057|9060|9061|9062|9063|9064|9067|9071|9072|9073|9074|9075|9076|9077|9078|9079|9081|9082|9083|9084|9086|9087|9088|9089|9091|9100|9101|9102|9103|9104|9105|9106|9107|9108|9109|9111|9112|9113|9114|9121|9122|9123|9124|9125|9131|9132|9133|9134|9135|9136|9137|9138|9141|9142|91439144|9145|9146|9147|9148|9150|9151|9152|9153|9154|9155|9156|9160|9161|9162|9163|9164|9166|9171|9172|9173|9174|9175|9176|9177|9178|9200|9201|9202|9203|9204|9205|9206|9207|9211|9212|9213|9214|9215|9216|9217|9218|9219|9221|9222|9223|9230|9231|9233|9240|9241|9243|9244|9245|9246|9247|9248|9249|9250|9251|9254|9255|9256|9257|9258|9260|9261|9262|9263|9264|9265|9269|9270|9271|9280|9281|9283|9284|9285|9286|9287|9288|9289|9290|9291|9292|9293|9294|9295|9296|9297|9298|9299|9851|9852|9853|9871|9872|9873|9950)\s*[a-zA-Z]{2}
I obviously tried the [^] function and the ?: function but I can't get it working properly.
Just break this string into a set(I think slice function can do that) then sort it and every time you get a value match if it exists in this set or not.
Lets make it easier, I am guessing you are getting numbers in string format of some sort with some form of separation in this case "|".
Step one create array by splinting string based on separator
Step two use filter function that will return a new array based on conditions you provide as shown in example.
Below example takes into consideration edge cases e.g. we are only comparing numbers alphabets are of lesser comparative value to us. What we have to make sure is any comparative value starts with number rest is is all gibberish. So extract number and run bit of magic on that.
Your sting was too long I have used a hypothetical scenario to give you what you want. Rest should be self explanatory in example.
data = '100|999|1000|s1000|10d00|1000f|2500|7500|10000|10001|10500';
dataArray = data.split("|");
dataFiltered = dataArray.filter(function (item) {
extractedNumber = item.match(/^\d+/g);
if(extractedNumber > 999 && extractedNumber <10001) {
return item;
}})
console.log(dataFiltered)
to check on whats being extracted run following and update function as needed.
data = '100|999|1000|s1000|10d00|1000f|2500|7500|10000|10001|10500';
dataArray = data.split("|");
dataFiltered = dataArray.filter(function (item) {
extractedNumber = item.match(/^\d+/);
console.log(extractedNumber);
if(extractedNumber > 999 && extractedNumber <10001) {
return item;
}})
console.log(dataFiltered)
What does the following code do and what is the use of it?
JavaScript
function removeHtmlTag(strx,chop){
if(strx.indexOf("<")!=-1)
{
var s = strx.split("<");
for(var i=0;i<s.length;i++){
if(s[i].indexOf(">")!=-1){
s[i] = s[i].substring(s[i].indexOf(">")+1,s[i].length);
}
}
strx = s.join("");
}
chop = (chop < strx.length-1) ? chop : strx.length-2;
while(strx.charAt(chop-1)!=' ' && strx.indexOf(' ',chop)!=-1) chop++;
strx = strx.substring(0,chop-1);
return strx+'...';
}
It parses HTML and removes tags in a manner that is really pretty loose. It can fail in certain circumstances. For example if there's a > inside an attribute value, or if there's a < in the text without a tag name directly after it, it'll mess up the result.
It also optionally truncates the text returned. The while loop ensures that the truncated text happens at a space character.
So if you pass it a string of HTML, aside from the problems I noted above, it'll give you back the string without the tags. And if you pass it a number as the second argument, it'll limit the length to that number (again, except that it'll add to it to avoid chopping a word in half).
I make a serialized list (with JQuery) and then want to delete a Parameter/Value pair from the list. What's the best way to do this? My code seems kinda clunky to take care of edge conditions that the Parameter/Value pair might be first, last, or in the middle of the list.
function serializeDeleteItem(strSerialize, strParamName)
{
// Delete Parameter/Value pair from Serialized list
var strRegEx;
var rExp;
strRegEx = "((^[?&]?" + strParamName + "\=[^\&]*[&]?))|([&]" + strParamName + "\=[^\&]*)|(" + strParamName + "\=[^\&]*[&])";
rExp = new RegExp(strRegEx, "i");
strSerialize = strSerialize.replace(rExp, "");
return strSerialize;
}
Examples / Test rig at http://jsfiddle.net/7Awzw/
EDIT: Modified the test rig to preserve any leading "?" or "&" so that function could be used with URL Query String or fragment of serialized string
See: http://jsfiddle.net/7Awzw/5/
This version is longer than yours, but imho it's more maintainable. It will find and remove the serialized parameter regardless of where it is in the list.
Notes:
To avoid problems with removing items in the middle of an array, we iterate in reverse.
For exact matching of parameter names, we expect them to start at the beginning of the split string, and to terminate with =.
Assuming there is just one instance of the given param, we break once it's found. If there may be more, just remove that line.
Code
function serializeDeleteItem(strSerialize, strParamName)
{
var arrSerialize = strSerialize.split("&");
var i = arrSerialize.length;
while (i--) {
if (arrSerialize[i].indexOf(strParamName+"=") == 0) {
arrSerialize.splice(i,1);
break; // Found the one and only, we're outta here.
}
}
return arrSerialize.join("&");
}
This fails a few of your tests - the ones with serialized strings starting with '?' or '&'. If you feel those are valid, then you could do this at the start of the function, and all tests will pass:
if (strSerialize.length && (strSerialize[0] == '?' || strSerialize[0] == '&'))
strSerialize = strSerialize.slice(1);
Performance Comparison
I've put together a test in jsperf to compare the regex approach with this string method. It's reporting that the regex solution is 49% slower than strings, in IE10 on 32-bit Win7.
I am looking to find the best possible way to find how many $ symbols are on a page. Is there a better method than reading document.body.innerHTML and calc how many $-as are on that?
Your question can be split into two parts:
How can we get the the webpage text content without HTML tags?
We can generalize the second question a bit.
How can we find the number of string occurrences in another string?
And the 'best possible way to do this':
Amaan got the idea right of finding the text, but lets take it further.
var text = document.body.innerText || document.body.textContent;
Adding textContent to the code helps us cover more browsers, since innerText is not supported by all of them.
The second part is a bit trickier. It all depends on the number of '$' symbol occurrences on the page.
For example, if we know for sure, that there is at least one occurrence of the symbol on the page we would use this code:
text.match(/\$/g).length;
Which performs a global regular expression match on the given string and counts the length of the returned array. It's pretty fast and concise.
On the other hand, if we're not sure if the symbol appears on the page at least once, we should modify the code to look like this:
if (match = text.match(/\$/g)) {
match.length;
}
This just checks the value returned by the match function and if it's null, does nothing.
I would recommend using the third option only when there is a large occurrence of the symbols in the page or you're going to perform the search many many times. This is a custom function (taken from here) to count the occurrence of the specified string in another string. It performs better than the other two, but is longer and harder to understand.
var occurrences = function(string, subString, allowOverlapping) {
string += "";
subString += "";
if (subString.length <= 0) return string.length + 1;
var n = 0,
pos = 0;
var step = (allowOverlapping) ? (1) : (subString.length);
while (true) {
pos = string.indexOf(subString, pos);
if (pos >= 0) {
n++;
pos += step;
} else break;
}
return (n);
};
occurrences(text, '$');
I'm also including a little jsfiddle 'benchmark' so you can compare these three different approaches yourself.
Also: No, there isn't a better way of doing this than just getting the body text and counting how many '$' symbols there are.
You should probably use document.body.innerText or document.body.textContent to avoid getting your HTML give you false positives.
Something like this should work:
document.body.innerText.match(/\$/g).length;
An alternate way I can think of, would be to use window.find like this:
var len = 0;
while(window.find('$') === true){
len++;
}
(This may be unreliable because it depends on where the user clicked last. It will work fine if you do it onload, before any user interaction.)
How do I specify an optional character in an input mask?
I found this masked input plugin http://digitalbush.com/projects/masked-input-plugin/ and these mask definitions.
$.mask.definitions['g']="[ ]";
$.mask.definitions['h']="[aApP]";
$.mask.definitions['i']="[mM]";
$.mask.definitions['2']="[0-1]";
$.mask.definitions['6']="[0-5]";
new_mask = "29:69";
$("#txtTime").mask(new_mask);
This defines an input mask for a 12 hour time format, e.g. 11:00. I'd like to allow the user to specify only one digit for the "hour". Instead of having to type 01:00, the user should be able to type 1:00. How do I do that?
You need to use ? for optional characters so in your case you should use "2?9:69".
Quote and example from the page you linked to in your question:
You can have part of your mask be optional. Anything listed after '?'
within the mask is considered optional user input. The common example
for this is phone number + optional extension.
jQuery(function($){
$("#phone").mask("(999) 999-9999? x99999");
});
You can use $.mask.definitions['g']="[0-9 ]";
I have a similar problem I am trying to solve for variable currency amounts ($0.00 - $10000.00), and I don't really understand how the plugin is working.
On the one hand, the $.mask.definitions['symbol'] = '???' bit looks like it's employing a regex fragment, based on the examples in the API reference, and somewhat confirmed by this part in the source, within the mask function's code:
$.each(mask.split(""), function (i, c) {
if (c == '?') {
len--;
partialPosition = i;
} else if (defs[c]) {
tests.push(new RegExp(defs[c]));
if (firstNonMaskPos == null)
firstNonMaskPos = tests.length - 1;
} else {
tests.push(null);
}
});
...On the other, a mask definition of []|[0-9] does not work (I am attempting to do empty string or 0-9, for those not literate in regex.) For reference, I am attempting to build a mask to fulfill the 0.00-10000.00 condition like oooo9.99, where o is []|[0-9].
Since the code confirms that this is based upon regexes, the null or range pattern should be working but aren't; this is a more obscure bug in the mask framework. Unless I am the one trying to do something incorrectly, which is also possible...