Using Javascript, .test and RegEx to evaluate a URL for /?s= - javascript

I want to test the URL http://example.com in a browser window for an empty search string, i.e http://example.com/search/?s=, but not match anything like /search/?s=withsearchterms that has any search terms after the /search/?s=, and then use an if statement and .addClass to display a div that warns that no search terms were entered.
I'm trying to use Javascript and g.test like below; the RegEx pattern is valid, according to several RegEx testers. But no luck:
var href = window.location.href;
var contains = /[\/?s=]+/g.test(href);
if (contains) {
$("#no-search-terms").addClass("display-block");
}
Is my RegEx wrong? Is my use of test wrong?
Edit 11/29/2020
This work, thanks to Heo:
var search = window.location.href;
var regex = /(?<=\/\?s=).*$/
var result=regex.exec( search )
if (result && result[0]=='') {
alert("The search terms are empty.");
} else {
alert("The search terms are not empty or no matched.");
}
But miknik's answer is much simpler with no need for regex. Works on Chrome 87, Firefox 83 and Safari 14:
const queries = new URLSearchParams(window.location.search)
if (queries.has("s") && queries.get("s").length == 0){
alert("The search terms are empty.");
}

You can test if end of string contains /?s=:
var url1 = 'https://example.com/?s=';
var url2 = 'https://example.com/?s=withsearchterms';
var regex = /\/\?s=$/;
console.log(url1 + ' ==> ' + regex.test(url1));
console.log(url2 + ' ==> ' + regex.test(url2));
Output:
https://example.com/?s= ==> true
https://example.com/?s=withsearchterms ==> false
Explanation:
\/\?s= - expect /?s=
$ - trailing $ anchors the regex at the end, e.g. preceding text must occur at the end
thus, the test returns true if the url has no search term (you can reverse your if test)

No need for regex here, something like this should work fine in modern browsers:
const queries = new URLSearchParams(window.location.search)
if (queries.has("s") && queries.get("s").length == 0){
// do stuff
}

Another alternative that (mostly) avoids regular expressions:
function isEmptySearch(urlString) {
const url = new URL(urlString);
const urlParams = url.search.replace(/^\?/, '').split('&').reduce( (acc, cur) => {
const param = cur.split('=');
acc[param[0]] = param[1];
return acc;
}, {});
return !urlParams.s;
}
const testUrls = [
"http://example.com/search/",
"http://example.com/search/?s=",
"http://example.com/search/?s=&foo=bar&baz",
"http://example.com/search/?s=hello&foo=bar&baz"
];
testUrls.forEach( url => console.log(`${url}: empty search = ${isEmptySearch(url)}`) );
I think I prefer the regex option presented earlier by Peter Thoeny as it's less verbose, but this version might be of interest.

If You want to use REGEX, you could use exec() instead of test() because the test function isn't good at the case.
Try this:
//URL-input
var href1 = 'http://example.com/?s='
var href2 = 'http://example.com/?s=xx'
var href3 = 'http://example.com/'
function alertsSearchString( href ){
var regex = /(?<=\/\?s=).*$/
var Container= regex.exec( href )
if ( Container!=null && Container[0]=='' )
alert( 'The search string is an empty string!' )
else if (Container!=null)
alert( 'The search string: ' + Container[0] )
else
alert( "The Container is "
+ Container
+", because input URL isn't matched the \nREGEX : "
+ regex.toString() )
}
//alerts-output
alertsSearchString( href1 )
alertsSearchString( href2 )
alertsSearchString( href3 )
Output:
First Alert : The search string is an empty string!
SecondAlert : The search string: xx
Third Alert : The Container is null because input URL isn't matched the
REGEX : /(?<=\/\?s=).*$/
Detail:
Regex expression: (?<=\/\?s=).*$
(?<=\/\?s=) use lookbehind to check and skip /?s=.
.* match zero to more characters after /?s=.
$ preceding text must occur at the end.
See regex-demo
The source below is an edited from your example Edit 11/22/2020 using exec()
var search = 'http://example.com/search/?s='
var regex = /(?<=\/\?s=).*$/
var result=regex.exec( search )
if (result && result[0]=='') {
alert("The search terms are empty.");
} else {
alert("The search terms are not empty or no matched.");
}

Forget regex, nodejs URL is your friend. https://nodejs.org/dist/latest-v14.x/docs/api/url.html#url_new_url_input_base
for legacy nodejs versions you can use url.parse and querystring.parse
const { URL } = require('url');
const url1 = new URL('https://example.com/?s=');
const url2 = new URL('https://example.com/?s=withsearchterms');
function hasEmptyQuery(u) {
return [...u.searchParams]
.some(([key, value]) => value.length === 0);
}
console.log(hasEmptyQuery(url1));
// true
console.log(hasEmptyQuery(url2));
// false

Related

Regex for URL/String - If protocol return false

Trying to create a regex in which the string should not start with http(s)://, http(s)://www. Rest of the string can be anything.
I used this regeg but its return true if we have http://
^(http://www.|https://www.|http://|https://)?[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?$
Another one I tried is
var re = new RegExp("(http|https|ftp)://");
var str = "http://xxxx.com";
var match = re.test(str);
console.log(match);
this one is also returning true.
Demo here
let re = /(http|https|ftp):///;
let url = 'xxxx.xxxx.xxxx'; // this is valid but test returns false
let url2 = 'https://www.xxzx.com/xxx.aspx'; // this should fail as there is https://www in url
console.log(re.test(url)); //
console.log(re.test(url2)); //
Is this possible with regex?
You need to use negative lookahead in your regex to discard strings starting with protocols like http or https or ftp. You can use this regex,
^(?!(?:ftp|https?):\/\/(www\.)?).+$
Regex Demo
JS Demo,
const arr = ['xxxx.xxxx.xxxx','ftp://www.xxzx.com/xxx.aspx','https://www.xxzx.com/xxx.aspx','http://xxxx.com','https://xxzx.com/xxx.aspx','http://www.xxxx.com']
arr.forEach(s => console.log(s + " --> " + /^(?!(?:ftp|https?):\/\/(www\.)?).+$/.test(s)))
It's probably possible to do with regexes, but unless you have to use a regex, you should use the URL class:
let HTTP_URL = 'https://www.xxzx.com/xxx.aspx'
let HTTPS_URL = 'https://www.xxzx.com/xxx.aspx'
let FTP_URL = 'ftp://www.xxzx.com/xxx.aspx'
let GOOD_PROTOCOL = 'mysql://www.xxzx.com/xxx.aspx'
let GOOD_INPUT = '129.123.12.123'
function test_url(url) {
let bad_protocols = ['http:', 'https:', 'ftp:']
try {
var parsed = new URL(url)
} catch {
return true
}
return (!bad_protocols.contains(parsed.protocol))
}
test_url(HTTP_URL) //false
test_url(HTTPS_URL) //false
test_url(FTP_URL) //false
test_url(GOOD_PROTOCOL) //true
test_url(GOOD_INPUT) //true
If you're just trying to negate that regex:
function doesMatch(string) {
return !/^http(s):\/\/(?:www)?/.test(string);
}
[
'https://www.xxzx.com/xxx.aspx',
'http://www.xxxx.com',
'https://xxxx.com',
'http://xxxx.com',
'https://aaaa.com',
'aaaa.com'
].forEach(s => console.log(doesMatch(s)));
In your example code, re.test(url) returns false , because there is no presence of http or https in that string.
In url2 (ie..'https://www.xxzx.com/xxx.aspx') , there is a presence of https so it is returning true.
This expression might also work, it would allow your desired input and fails all other URLs, and you can also simply add to its char list, what else might be undesired to start:
^([^http|s|ftp|www|\/\/|])*
Pass
xxxx.xxxx.xxxx
Fail
ftp://www.xxzx.com/xxx.aspx
https://www.xxzx.com/xxx.aspx
http://xxxx.com
https://xxzx.com/xxx.aspx
http://www.xxxx.com
//www.xxxx.com
You can test/modify/change it in this link.
RegEx Descriptive Graph
This graph shows how the expression would work and you can visualize other expressions in this link:
Performance Test
This JavaScript snippet shows the performance of that expression using a simple 1-million times for loop.
const repeat = 1000000;
const start = Date.now();
for (var i = repeat; i >= 0; i--) {
const string = 'xxxx.xxxx.xxxx';
const regex = /(^([^http|s|ftp|www|\/\/|])*)/gm;
var match = string.replace(regex, "$1");
}
const end = Date.now() - start;
console.log("YAAAY! \"" + match + "\" is a match 💚💚💚 ");
console.log(end / 1000 + " is the runtime of " + repeat + " times benchmark test. 😳 ");

Match a string and get what is after the match

I have this content from a torrent file
d8:announce39:http://torrent.ubuntu.com:6969/announce13:announce-listll39:http://torrent.ubuntu.com:6969/announceel44:http://ipv6.torrent.ubuntu.com:6969/announceee7:comment29:Ubuntu CD releases.ubuntu.com13:creation datei1539860537e4:infod6:lengthi1999503360e4:name30:ubuntu-18.10-desktop-amd64.iso12:piece lengthi524288e6:pieces76280
or I can have also
d8:announce39:http://torrent.centos.org:6969/announce13:announce-listll39:http://torrent.centos.org:6969/announceel44:http://ipv6.torrent.centos.org:6969/announceee7:comment27:CentOS x86_64 LiveGNOME ISO10:created by13:mktorrent 1.013:creation datei1526053398e4:infod5:filesld6:lengthi1388314624e4:pathl34:CentOS-7-x86_64-LiveGNOME-1804.isoeed6:lengthi454e4:pathl11:sha1sum.txteed6:lengthi1314e4:pathl15:sha1sum.txt.asceed6:lengthi598e4:pathl13:sha256sum.txteed6:lengthi1458e4:pathl17:sha256sum.txt.asceee4:name30:CentOS-7-x86_64-LiveGNOME-180412:piece lengthi524288e6:pieces52980:
I want to retrieve the name part like ubuntu-18.10-desktop-amd64.iso
Here is what I tried but it check the full content :
$.get('search', function(data) {
var lines = data.split("\n");
var $result = false
var url_check
var search= [];
$.each(lines, function(n, data) {
search.push(data)
})
}).done(function(search){
search= search.split("\n");
var $result = [];
$.each(search, function(n, search) {
var regex = new RegExp('^(?=.*' + search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').split(/\\?[\s,_.:*-]+/).join(')(?=.*') + ')', 'gi');
if(regex.test(url_check) === true){
$result.push('true');
}else{
$result.push('false');
}
})
console.log($result)
if($result.indexOf("true") !== -1){
alert('Found !')
}else {
alert('Not found !');
}
})
Content of the file search :
*Ubuntu.18*
*centos 7*
According to the BitTorrent specification, those trailing digits match the length of the following string. For example
ubuntu-18.10-desktop-amd64.iso
is 30 characters long, thus the number that comes before it is 30:
30:ubuntu-18.10-desktop-amd64.iso
So, a pure regex solution won't really work, at least not in any concise fashion. You could extract the name<digits>: and the rest of the string following it, and then in Javascript use slice to extract <digits> number of characters after the colon:
const input = [
'd8:announce39:http://torrent.ubuntu.com:6969/announce13:announce-listll39:http://torrent.ubuntu.com:6969/announceel44:http://ipv6.torrent.ubuntu.com:6969/announceee7:comment29:Ubuntu CD releases.ubuntu.com13:creation datei1539860537e4:infod6:lengthi1999503360e4:name30:ubuntu-18.10-desktop-amd64.iso12:piece lengthi524288e6:pieces76280',
'd8:announce39:http://torrent.centos.org:6969/announce13:announce-listll39:http://torrent.centos.org:6969/announceel44:http://ipv6.torrent.centos.org:6969/announceee7:comment27:CentOS x86_64 LiveGNOME ISO10:created by13:mktorrent 1.013:creation datei1526053398e4:infod5:filesld6:lengthi1388314624e4:pathl34:CentOS-7-x86_64-LiveGNOME-1804.isoeed6:lengthi454e4:pathl11:sha1sum.txteed6:lengthi1314e4:pathl15:sha1sum.txt.asceed6:lengthi598e4:pathl13:sha256sum.txteed6:lengthi1458e4:pathl17:sha256sum.txt.asceee4:name30:CentOS-7-x86_64-LiveGNOME-180412:piece lengthi524288e6:pieces52980:'
];
function getName(str) {
const match = str.match(/:name(\d+):(.+)$/);
if (!match) {
return console.log('No name found');
}
const [, length, rest] = match;
console.log(
rest.slice(0, length)
);
}
input.forEach(getName)
If there may be line-terminators in the string, then (.+)$ won't work because . does not match newlines - either remove the $, or, if there may be newlines in the name that you want to match, use ([\s\S]+)$ instead, to match any character, including newlines.

Get values from window location . url

I have response url in window.location.href and I need the value for error, error_description and state from it
http://localhost:4200/#error=access_denied&error_description=AADB2C90118%3a+The+user+has+forgotten+their+password.%0d%0aCorrelation+ID%3a+a7916eb9-4404-4cc5-b5a3-ee3211237566%0d%0aTimestamp%3a+2018-02-05+09%3a19%3a07Z%0d%0alogin_hint%3a+kzahid%40opm.co.uk%0d%0a&state=da2d6e3c-cb6f-1d3b-909b-c6412325b3
I am using following code but getting null value
var messageType = new RegExp('[\?&]' + "error" + '=([^&#]*)').exec(window.location.href);
I need find this string from url "The user has forgotten their password"
Your problem here is that your URL parameters are preceded by a #, not a ?.
So, simply replace it and access the parameters using URLSearchParams#get():
var prevUrl = "http://localhost:4200/#error=access_denied&error_description=AADB2C90118%3a+The+user+has+forgotten+their+password.%0d%0aCorrelation+ID%3a+a7916eb9-4404-4cc5-b5a3-ee3211237566%0d%0aTimestamp%3a+2018-02-05+09%3a19%3a07Z%0d%0alogin_hint%3a+kzahid%40opm.co.uk%0d%0a&state=da2d6e3c-cb6f-1d3b-909b-c6412325b3";
var url = new URL(prevUrl.replace(/#/,'?'));
console.log(url.searchParams.get("error"));
console.log(url.searchParams.get("error_description"));
In a (modern) browser you can use the new URL() to parse your url and extract query parameters easily.
var location_url="http://localhost:4200/#error=access_denied&error_description=AADB2C90118%3a+The+user+has+forgotten+their+password.%0d%0aCorrelation+ID%3a+a7916eb9-4404-4cc5-b5a3-ee3211237566%0d%0aTimestamp%3a+2018-02-05+09%3a19%3a07Z%0d%0alogin_hint%3a+kzahid%40opm.co.uk%0d%0a&state=da2d6e3c-cb6f-1d3b-909b-c6412325b3";
//To make it work you have to replace "/#" with '?' so that new URL() constructor parses the url properly.
location_url=location_url.replace('\/#','?');
var url = new URL(location_url);
var error = url.searchParams.get("error");
console.log(error);
You could split by & and then split items by =.
// what you would do:
//const hash = location.hash;
// for demo purposes:
const hash = '#error=access_denied&error_description=AADB2C90118%3a+The+user+has+forgotten+their+password.%0d%0aCorrelation+ID%3a+a7916eb9-4404-4cc5-b5a3-ee3211237566%0d%0aTimestamp%3a+2018-02-05+09%3a19%3a07Z%0d%0alogin_hint%3a+kzahid%40opm.co.uk%0d%0a&state=da2d6e3c-cb6f-1d3b-909b-c6412325b3';
const hashParams = hash.substr(1).split('&')
.reduce((obj, groupStr) =>
Object.assign(obj, {
[groupStr.split('=')[0]]: groupStr.split('=')[1]
}), {});
console.log(hashParams);
console.log(hashParams.error_description);
use reg like this:
let url='http://localhost:4200/#error=access_denied&error_description=AADB2C90118%3a+The+user+has+forgotten+their+password.%0d%0aCorrelation+ID%3a+a7916eb9-4404-4cc5-b5a3-ee3211237566%0d%0aTimestamp%3a+2018-02-05+09%3a19%3a07Z%0d%0alogin_hint%3a+kzahid%40opm.co.uk%0d%0a&state=da2d6e3c-cb6f-1d3b-909b-c6412325b3';
let result=url.match(/error_description=([\s\S]*?)\./)[1].split('+');
result.shift();
console.log(result.join(' '));
If you still want to use a RegExp even though might be an overkill having the new options from the previous answers, you can use a RegExp like this:
const regex = /(error|error_description)=(.+?)&/g;
const str = `http://localhost:4200/#error=access_denied&error_description=AADB2C90118%3a+The+user+has+forgotten+their+password.%0d%0aCorrelation+ID%3a+a7916eb9-4404-4cc5-b5a3-ee3211237566%0d%0aTimestamp%3a+2018-02-05+09%3a19%3a07Z%0d%0alogin_hint%3a+kzahid%40opm.co.uk%0d%0a&state=da2d6e3c-cb6f-1d3b-909b-c6412325b3`;
let matches;
while ((matches = regex.exec(str)) !== null) {
if (matches.index === regex.lastIndex) {
regex.lastIndex++;
}
matches.forEach((match, groupIndex) => {
if (groupIndex === 1 )
console.log(`Param: ${match}`);
if (groupIndex === 2 )
console.log(`Value: ${match}`);
});
}
/(error|error_description)=(.+?)&/g
Here you have 2 capture groups inside the full match, so you can get separatedly the parameter name and its value.
(error|error_description) -> will match either error or error_description
(.+?) -> will match from 1 to any characters until it finds the next character match, stated in this case by &, as few times as possible and expanding as needed
The g (global modifier) will allow to return all the matches found.

Remove all dots except the first one from a string

Given a string
'1.2.3.4.5'
I would like to get this output
'1.2345'
(In case there are no dots in the string, the string should be returned unchanged.)
I wrote this
function process( input ) {
var index = input.indexOf( '.' );
if ( index > -1 ) {
input = input.substr( 0, index + 1 ) +
input.slice( index ).replace( /\./g, '' );
}
return input;
}
Live demo: http://jsfiddle.net/EDTNK/1/
It works but I was hoping for a slightly more elegant solution...
There is a pretty short solution (assuming input is your string):
var output = input.split('.');
output = output.shift() + '.' + output.join('');
If input is "1.2.3.4", then output will be equal to "1.234".
See this jsfiddle for a proof. Of course you can enclose it in a function, if you find it necessary.
EDIT:
Taking into account your additional requirement (to not modify the output if there is no dot found), the solution could look like this:
var output = input.split('.');
output = output.shift() + (output.length ? '.' + output.join('') : '');
which will leave eg. "1234" (no dot found) unchanged. See this jsfiddle for updated code.
It would be a lot easier with reg exp if browsers supported look behinds.
One way with a regular expression:
function process( str ) {
return str.replace( /^([^.]*\.)(.*)$/, function ( a, b, c ) {
return b + c.replace( /\./g, '' );
});
}
You can try something like this:
str = str.replace(/\./,"#").replace(/\./g,"").replace(/#/,".");
But you have to be sure that the character # is not used in the string; or replace it accordingly.
Or this, without the above limitation:
str = str.replace(/^(.*?\.)(.*)$/, function($0, $1, $2) {
return $1 + $2.replace(/\./g,"");
});
You could also do something like this, i also don't know if this is "simpler", but it uses just indexOf, replace and substr.
var str = "7.8.9.2.3";
var strBak = str;
var firstDot = str.indexOf(".");
str = str.replace(/\./g,"");
str = str.substr(0,firstDot)+"."+str.substr(1,str.length-1);
document.write(str);
Shai.
Here is another approach:
function process(input) {
var n = 0;
return input.replace(/\./g, function() { return n++ > 0 ? '' : '.'; });
}
But one could say that this is based on side effects and therefore not really elegant.
This isn't necessarily more elegant, but it's another way to skin the cat:
var process = function (input) {
var output = input;
if (typeof input === 'string' && input !== '') {
input = input.split('.');
if (input.length > 1) {
output = [input.shift(), input.join('')].join('.');
}
}
return output;
};
Not sure what is supposed to happen if "." is the first character, I'd check for -1 in indexOf, also if you use substr once might as well use it twice.
if ( index != -1 ) {
input = input.substr( 0, index + 1 ) + input.substr(index + 1).replace( /\./g, '' );
}
var i = s.indexOf(".");
var result = s.substr(0, i+1) + s.substr(i+1).replace(/\./g, "");
Somewhat tricky. Works using the fact that indexOf returns -1 if the item is not found.
Trying to keep this as short and readable as possible, you can do the following:
JavaScript
var match = string.match(/^[^.]*\.|[^.]+/g);
string = match ? match.join('') : string;
Requires a second line of code, because if match() returns null, we'll get an exception trying to call join() on null. (Improvements welcome.)
Objective-J / Cappuccino (superset of JavaScript)
string = [string.match(/^[^.]*\.|[^.]+/g) componentsJoinedByString:''] || string;
Can do it in a single line, because its selectors (such as componentsJoinedByString:) simply return null when sent to a null value, rather than throwing an exception.
As for the regular expression, I'm matching all substrings consisting of either (a) the start of the string + any potential number of non-dot characters + a dot, or (b) any existing number of non-dot characters. When we join all matches back together, we have essentially removed any dot except the first.
var input = '14.1.2';
reversed = input.split("").reverse().join("");
reversed = reversed.replace(\.(?=.*\.), '' );
input = reversed.split("").reverse().join("");
Based on #Tadek's answer above. This function takes other locales into consideration.
For example, some locales will use a comma for the decimal separator and a period for the thousand separator (e.g. -451.161,432e-12).
First we convert anything other than 1) numbers; 2) negative sign; 3) exponent sign into a period ("-451.161.432e-12").
Next we split by period (["-451", "161", "432e-12"]) and pop out the right-most value ("432e-12"), then join with the rest ("-451161.432e-12")
(Note that I'm tossing out the thousand separators, but those could easily be added in the join step (.join(','))
var ensureDecimalSeparatorIsPeriod = function (value) {
var numericString = value.toString();
var splitByDecimal = numericString.replace(/[^\d.e-]/g, '.').split('.');
if (splitByDecimal.length < 2) {
return numericString;
}
var rightOfDecimalPlace = splitByDecimal.pop();
return splitByDecimal.join('') + '.' + rightOfDecimalPlace;
};
let str = "12.1223....1322311..";
let finStr = str.replace(/(\d*.)(.*)/, '$1') + str.replace(/(\d*.)(.*)/, '$2').replace(/\./g,'');
console.log(finStr)
const [integer, ...decimals] = '233.423.3.32.23.244.14...23'.split('.');
const result = [integer, decimals.join('')].join('.')
Same solution offered but using the spread operator.
It's a matter of opinion but I think it improves readability.

Determining whether values can potentially match a regular expression, given more input

I am currently writing an application in JavaScript where I'm matching input to regular expressions, but I also need to find a way how to match strings to parts of the regular expressions.
For example:
var invalid = "x",
potentially = "g",
valid = "ggg",
gReg = /^ggg$/;
gReg.test(invalid); //returns false (correct)
gReg.test(valid); //returns true (correct)
Now I need to find a way to somehow determine that the value of the potentially variable doesn't exactly match the /^ggg$/ expression, BUT with more input, it potentially can!
So for example in this case, the potentially variable is g, but if two more g's are appended to it, it will match the regular expression /^ggg$/
But in the case of invalid, it can never match the /^ggg$/ expression, no matter how many characters you append to it.
So how can I determine if a string has or doesn't have potential to match a particular regular expression?
Try this:
var str = "abcdefgh";
var len = str.length;
var reg = "";
for(var i = str.length - 1; i > 0; i--)
{
//replace '(' with '(?:' to make it non capturing.
reg = '(' + str[i] + reg + ')?';
}
reg = "^" + str[0] + reg + "$";
var regex = new RegExp(reg);
How about you simply "reverse" your thinking on this, and turn the "potential" into a regex, testing in the other direction, eg
var invalid = "x",
potentially = "g",
valid = "ggg",
validReg = new RegExp("^"+valid+"$"),
invalidReg = new RegExp(invalid),
potentialReg = new RegExp(potentially);
//test actual matches
validReg.test(invalid); //returns false (correct)
validReg.test(valid); //returns true (correct)
//test potential matches
potentialReg.test(valid); //returns true
invalidReg.test(valid); //returns false
Obviously the test function below isn't going to be exactly what you want ... hopefully it will give you an idea as to how to tackle the problem.
function test(reg,string){
var r = reg.exec(string);
if(r){
if(r.pop()){
return true;
}
return "potentially";
}
return false;
}
var invalid = "x",
potentially = "a",
potentially2 = "ab",
valid = "abc",
gReg = /^a(b(c)?)?$/;
alert(test(gReg,invalid)); //returns false (correct)
alert(test(gReg,potentially)); //returns "potentially" (correct)
alert(test(gReg,potentially2)); //returns "potentially" (correct)
alert(test(gReg,valid)); //returns true (correct)
There is no general solution. If the regexp is a simple string, like the one in the example (in which case there is no point in using a regexp at all), you can use simple string comparision:
var invalid = "x",
potentially = "g",
valid = "ggg";
var gReg = "ggg";
function test(t, s) {
if (t === s) return true;
if (t.indexOf(s) === 0) return "potentially";
return false;
}
test(gReg, invalid); // false
test(gReg, potentially); // "potentially"
test(gReg, valid); // true
Otherwise you can manually construct another regexp which accepts every prefix of every string gReg accepts. You will have to use ()? a lot.
function have_potential(input, valid) {
if ( (new RegExp('^' + valid + '$')).test(input) ) return false;
if ( (new RegExp(input)).test( valid ) ) return true;
return false;
}
var valid = 'aaa|bbb';
console.log( have_potential('a',valid) )
// true
console.log( have_potential('c',valid) )
// false
console.log( have_potential('aaa',valid) )
// false
Edit:
shorten version
function have_potential(input, valid) {
return ( (new RegExp(input)).test( valid ) && !(new RegExp('^' + valid + '$')).test(input) );
}
Edit2:
indexOf would be better in first place. function requires flat string inputs and "valid" may contain a list separated by "|"
function have_potential(input, valid) {
return ( valid.indexOf(input) !== -1 && !(new RegExp('^' + valid + '$')).test(input) );
}

Categories

Resources