Determine token value by comparing with token replaced string - javascript

I have a tokenised string like so;
var route = a/b/{firstId}/c/d/{nextId}
and I am wondering if it is possible with regex to get the value of "firstId" via a second string with tokens already replaced.
Example, if I have a given string;
var partPath = a/b/33
I can do something like;
function getValueFromPath(path, route){
//regex stuff
return tokenValue; //Expected result 33
}
getValueFromPath(partPath, route);
Thank you,
C.

A regex solution would be overly complicated (if you didn't define the route with a regexp right away). I'd just use
function getValueFromPath(path, route){
var actualParts = path.split("/"),
expectedParts = route.split("/"),
result = {};
for (var i=0; i<expectedParts.length; i++) {
if (i >= actualParts.length)
return result;
var actual = actualParts[i],
expected = expectedParts[i];
if (/^\{.+\}$/.test(expected))
result[ expected.slice(1, -1) ] = actual;
else if (actual != expected)
// non-matching literals found, abort
return result;
}
return result;
}
> getValueFromPath("a/b/33", "a/b/{firstId}/c/d/{nextId}")
{firstId: "33"}
> getValueFromPath("a/b/33/c/d/42/x", "a/b/{firstId}/c/d/{nextId}")
{firstId: "33", nextId: "42"}
Here's the same thing with "regex stuff" (notice that regex special characters in the route are not escaped, you have to take care about that yourself):
function getValueFromPath(path, route){
var keys = [];
route = "^"+route.split("/").reduceRight(function(m, part) {
return part + "(?:/" + m + ")?"; // make right parts optional
}).replace(/\{([^\/{}]+)\}/g, function(m, k) {
keys.push(k); // for every "variable"
return "([^/]+)"; // create a capturing group
});
var regex = new RegExp(route); // build an ugly regex:
// regex == /^a(?:\/b(?:\/([^/]+)(?:\/c(?:\/d(?:\/([^/]+))?)?)?)?)?/
var m = path.match(regex),
result = {};
for (var i=0; m && i<keys.length; i++)
result[keys[i]] = m[i+1];
return result;
}

You can create a regexp like this:
function getValueFromPath(path, route){
tokenValue = path.match(route)[1];
return tokenValue; //Expected result 33
}
var route = /\/a\/b\/([^\/]+)(\/c\/d\/([^\/]+))?/;
var partPath = '/a/b/33';
getValueFromPath(partPath, route); // == 33
http://jsfiddle.net/firstclown/YYvvn/2/
This will let you extract the first value at the first match with [1] and you can get the nextId by changing that to [3] (since [2] will give you the whole path after the 33).

Related

Why does RegExp exec() not work properly in my case? [duplicate]

This question already has answers here:
Why does a RegExp with global flag give wrong results?
(7 answers)
Closed 3 years ago.
If the RegExp is defined global and I use the vals array like I do, the result of exec will be the same everytime, so the code below is an infinity loop.
var regex = RegExp(/<(.*?)>.*?<\/\1>/, "g");
function readXml(xmlString) {
var obj = {};
var vals;
for (var i = 0;
(vals = regex.exec(xmlString)) !== null; i++) {
if (!obj[vals[1]]) obj[vals[1]] = [];
obj[vals[1]].push(readXml(vals[0].slice(vals[1].length + 1, -vals[1] - length - 3)));
}
if (i == 0) return xmlString;
return obj;
}
console.log(readXml("<a>a</a><b>b</b>"));
If the RegExp is defined in function, the result of exec will be the next match everytime, so the code below logs a and b.
function readXml(xmlString) {
var regex = RegExp(/<(.*?)>.*?<\/\1>/, "g");
var obj = {};
var vals;
for (var i = 0;
(vals = regex.exec(xmlString)) !== null; i++) {
if (!obj[vals[1]]) obj[vals[1]] = [];
obj[vals[1]].push(readXml(vals[0].slice(vals[1].length + 1, -vals[1] - length - 3)));
}
if (i == 0) return xmlString;
return obj;
}
console.log(readXml("<a>a</a><b>b</b>"));
If I do something else with vals arrray in the loop, the result of exec will be the next match everytime, so the code below logs an empty object.
var regex = RegExp(/<(.*?)>.*?<\/\1>/, "g");
function readXml(xmlString) {
var obj = {};
var vals;
for (var i = 0;
(vals = regex.exec(xmlString)) !== null; i++) {
vals = [2]
}
if (i == 0) return xmlString;
return obj;
}
console.log(readXml("<a>a</a><b>b</b>"));
I think it should be an object with a and b in the first case too.
Why doesn't it just do the same thing in all cases?
Global regexes (ie. using the g flag) keep track of the position of the last match in order to successfully get the next one the next time you call exec. It makes the assumption that you're passing the same input string each time, but if you go and change the input then it goes weird.
const regex = RegExp(/./,'g'); // should match each character, one at a time.
let input1 = 'test', match;
match = regex.exec(input1);
console.log(match[0]);
// now let's "re-use" the regex object...
let input2 = 'another test';
match = regex.exec(input2);
console.log(match[0]);
console.log("Where did the `a` go??");
You can access and modify the property responsible for this behaviour via regex.lastIndex, although in this case your best solution is to create a new RegExp object within the function, since you're working recursively.

How to efficiently check if any substring in an array is contained in another string

I want to have something that checks if any substring in a list of strings is included in string. I have something that works, but I'm hoping there is something cleaner and more efficient, preferably just in one line I can call like if(string.contains(list.any)) or something.
var list = ['aa','bb','cc','dd'];
var string = "nygaard"; // true because "aa" is in "nygaard".
for (var i = 0; i < list.length; i++) {
if( string.indexOf( list[i] ) > -1 ) {
alert("True");
break;
}
}
var list = ['aa','bb','cc','dd'];
var string = "nygaard";
var patt = new RegExp(list.join('|'))
// regEx - /aa|bb|cc|dd/
patt.test(string)
//output true
Demo
Explanation
Dynamically create a regEx using new RegExp
for checking existance of multiple SubString we have | operator in RegEx
Use Array.join('|') to dynamically make a regExp like this aa|bb|cc
use test func to validate String
Edit - For Complex Cases - Problem is strings in list may have to be escaped for RegEx to work, Pointed By - #GabrielRatener
Compairing to my solu, #GabrielRatener's solution is better
var list = ['aa','bb','cc','dd', 'ab?', '(aa)'];
list = list.sort(function(a, b) {
if (a>b) return -1;
else if (a<b) return 1;
else return 0;
});
list = list.join(" ").replace(/[^\w\s]/g, function($1) {
return '\\' + $1
}).split(/\s/);
//["dd", "cc", "bb", "ab\?", "aa", "\(aa\)"]
//sorting needed to match "ab?" before single "a" as "b" will become optional
//due to "?"
//after processing
var string = "nygaard";
var patt = new RegExp(list.join('|')) // RegExp -> /dd|cc|bb|ab\?|aa|\(aa\)/
patt.test(string)
//true
Why not just put your loop in its own function you can call?
function stringContains(string, list) {
for (var i = 0; i < list.length; i++) {
if( string.indexOf( list[i] ) > -1 )
return true;
}
return false;
}
and then call it like this:
var list = ['aa','bb','cc','dd'];
var string = "nygaard";
if(stringContains(string, list))
alert("True");
If you're looking for a javascript library function, I don't believe there is one.
EcmaScript 6 is proposing a contains method for strings such that you could do this:
function stringContainsArray(str, array){
for (var i = 0; i < array.length; i++){
if (str.contains(array[i])){
return true;
}
}
return false;
}
var list = ['aa','bb','cc','dd'];
var string = "nygaard"; // true because "aa" is in "nygaard".
console.log(stringContainsArray(list));
// => true
Since implementation will likely remain spotty in the major browsers and other runtimes for the near future, you should add the following code for compatibility before the stringContainsArray function:
// String.prototype.contains will be implemented in
// the major browsers in the not too distant future
// this will add the same functionality to browsers
// or other runtimes that do not currently support it
if ( !String.prototype.contains ) {
String.prototype.contains = function() {
return String.prototype.indexOf.apply( this, arguments ) !== -1;
};
}
this may help: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/contains
You can also extend the string prototype to have a simple method:
String.prototype.containsArray = function(array){
return stringContainsArray(this, array);
}
Then you can simpy do:
"nygaard".containsArray(list);
// => true

Replace text but keep case

I have a set of strings that I need to replace, but I need to keep the case of letters.
Both the input words and output words are of the same length.
For example, if I need to replace "abcd" with "qwer", then the following should happen:
"AbcD" translates to "QweR"
"abCd" translates to "qwEr"
and so on.
Right now I'm using JavaScript's replace, but capital letters are lost on translation.
r = new RegExp( "(" + 'asdf' + ")" , 'gi' );
"oooAsdFoooo".replace(r, "qwer");
Any help would be appreciated.
Here’s a helper:
function matchCase(text, pattern) {
var result = '';
for(var i = 0; i < text.length; i++) {
var c = text.charAt(i);
var p = pattern.charCodeAt(i);
if(p >= 65 && p < 65 + 26) {
result += c.toUpperCase();
} else {
result += c.toLowerCase();
}
}
return result;
}
Then you can just:
"oooAsdFoooo".replace(r, function(match) {
return matchCase("qwer", match);
});
I'll leave this here for reference.
Scenario: case-insensitive search box on list of items, partial match on string should be displayed highlighted but keeping original case.
highlight() {
const re = new RegExp(this.searchValue, 'gi'); // global, insensitive
const newText = name.replace(re, `<b>$&</b>`);
return newText;
}
the $& is the matched text with case
String.prototype.translateCaseSensitive = function (fromAlphabet, toAlphabet) {
var fromAlphabet = fromAlphabet.toLowerCase(),
toAlphabet = toAlphabet.toLowerCase(),
re = new RegExp("[" + fromAlphabet + "]", "gi");
return this.replace(re, function (char) {
var charLower = char.toLowerCase(),
idx = fromAlphabet.indexOf(charLower);
if (idx > -1) {
if (char === charLower) {
return toAlphabet[idx];
} else {
return toAlphabet[idx].toUpperCase();
}
} else {
return char;
}
});
};
and
"AbcD".translateCaseSensitive("abcdefg", "qwertyu")
will return:
"QweR"
Here's a replaceCase function:
We turn the input pattern into a regular expression
We have a nested replacer function which iterates through every character
We use regular expression /[A-Z]/ to identify capital letters, otherwise we assume everything is in lowercase
function replaceCase(str, pattern, newStr) {
const rx = new RegExp(pattern, "ig")
const replacer = (c, i) => c.match(/[A-Z]/) ? newStr[i].toUpperCase() : newStr[i]
return str.replace(rx, (oldStr) => oldStr.replace(/./g, replacer) )
}
let out = replaceCase("This is my test string: AbcD", "abcd", "qwer")
console.log(out) // This is my test string: QweR
out = replaceCase("This is my test string: abCd", "abcd", "qwer")
console.log(out) // This is my test string: qwEr
You could create your own replace function such as
if(!String.prototype.myreplace){
String.prototype.myreplace = (function(obj){
return this.replace(/[a-z]{1,1}/gi,function(a,b){
var r = obj[a.toLowerCase()] || a;
return a.charCodeAt(0) > 96? r.toLowerCase() : r.toUpperCase();
});
});
}
This takes in a object that maps different letters. and it can be called such as follows
var obj = {a:'q',b:'t',c:'w'};
var s = 'AbCdea';
var n = s.myreplace(obj);
console.log(n);
This means you could potentially pass different objects in with different mappings if need be. Here's a simple fiddle showing an example (note the object is all lowercase but the function itself looks at case of the string as well)
Expanding on Ryan O'Hara's answer, the below solution avoids using charCodes and the issues that maybe encountered in using them. It also ensures the replacement is complete when the strings are of different lengths.
function enforceLength(text, pattern, result) {
if (text.length > result.length) {
result = result.concat(text.substring(result.length, text.length));
}
if (pattern.length > text.length) {
result = result.substring(0, text.length);
}
return result;
}
function matchCase(text, pattern){
var result = '';
for (var i =0; i < pattern.length; i++){
var c = text.charAt(i);
var p = pattern.charAt(i);
if(p === p.toUpperCase()) {
result += c.toUpperCase();
} else {
result += c.toLowerCase();
}
}
return enforceLength(text, pattern, result);
}
This should replace while preserving the case. Please let me know if anyone finds any flaws in this solution. I hope this helps. Thank-you!
function myReplace(str, before, after) {
var match=function(before,after){
after=after.split('');
for(var i=0;i<before.length;i++)
{
if(before.charAt(i)==before[i].toUpperCase())
{
after[i]=after[i].toUpperCase();
}
else if(before.charAt(i)==before[i].toLowerCase())
{
after[i]=after[i].toLowerCase();
}
return after.join('');
}
};
console.log(before,match(before,after));
str =str.replace(before,match(before,after));
return str;
}
myReplace("A quick brown fox jumped over the lazy dog", "jumped", "leaped");
I had a sentence where I had to replace each word with another word and that word can be longer/shorter than the word its replacing so its similar to the question but instead of a fixed length, they're dynamic.
My solution
For simplicity, I am focusing on a single word.
const oldWord = "tEsT";
const newWord = "testing";
Split both words so that I can iterate over each individual letters.
const oldWordLetters = oldWord.split("");
const newWordLetters = newWord.split("");
Now, I would iterate over the newWord letters and use its index to then get the corresponding oldWord letter in the same position. Then I would check if the old letter is capital and if it is then make the new letter in the same position capital as well.
for (const [i, letter] of newWordLetters.entries()) {
const oldLetter = oldWordLetters[i];
// stop iterating if oldWord is shorter (not enough letters to copy case).
if (!oldLetter) {
break;
}
const isCapital = oldLetter === oldLetter.toUpperCase();
// make the new letter in the same position as the old letter capital
if (isCapital) {
newWordLetters[i] = letter.toUpperCase();
}
}
The final world would be tEsTing after joining the letters again.
const finalWord = newWordLetters.join("");
console.log(finalWord); // "tEsTing"
Full code
const oldWord = "tEsT";
const newWord = "testing";
const oldWordLetters = oldWord.split("");
const newWordLetters = newWord.split("");
for (const [i, letter] of newWordLetters.entries()) {
const oldLetter = oldWordLetters[i];
// stop iterating if oldWord is shorter (not enough letters to copy case).
if (!oldLetter) {
break;
}
const isCapital = oldLetter === oldLetter.toUpperCase();
// make the new letter in the same position as the old letter capital
if (isCapital) {
newWordLetters[i] = letter.toUpperCase();
}
}
const finalWord = newWordLetters.join("");
console.log(finalWord);
I think this could work
function formatItem(text, searchText){
const search = new RegExp(escapeRegExp(searchText), 'iu')
return text?.toString().replace(search, (m) => `<b>${m}</b>`)
}
function escapeRegExp(text) {
return text?.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') ?? '';
}
Thank you for asking this. I had the same problem when I wanted to search text and replace certain words with links, which was a slightly more specific situation because it is replacing text strings with html strings. I'll put my solution here in case anyone who finds this is doing anything similar.
let elmt = document.getElementById('the-element');
let a = document.createElement('a');
a.href = "https://www.example.com";
let re = new RegExp('the string to find', 'gi');
elmt.innerHTML = elmt.innerHTML.replaceAll(re, function (match) {
a.innerText = match;
return a.outerHTML;
});
So the regular expression ensures that it searches for case-insensitive matches, and the function as the second argument of the replaceAll function specifies that it is supposed to set the innerText of the new tag equal to the old string verbatim, before then returning the outerHTML of the whole tag.
Here is a replaceAllCaseSensitive function. If your want, you can change replaceAll by replace.
const replaceAllCaseSensitive = (
text, // Original string
pattern, // RegExp with the pattern you want match. It must include the g (global) and i (case-insensitive) flags.
replacement // string with the replacement
) => {
return text.replaceAll(pattern, (match) => {
return replacement
.split("")
.map((char, i) =>
match[i] === match[i].toUpperCase() ? char.toUpperCase() : char
)
.join("");
});
};
console.log(replaceAllCaseSensitive("AbcD abCd", /abcd/gi, "qwer"));
// outputs "QweR qwEr"
console.log(replaceAllCaseSensitive("AbcD abCd", /abcd/gi, "qwe"));
// outputs "Qwe qwE"
The function works even if replacement is shorter than match.

Parse query string in JavaScript [duplicate]

This question already has answers here:
How can I get query string values in JavaScript?
(73 answers)
Closed 3 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Duplicate This question has been answered, is not unique, and doesn’t differentiate itself from another question.
I need to parse the query string www.mysite.com/default.aspx?dest=aboutus.aspx.
How do I get the dest variable in JavaScript?
Here is a fast and easy way of parsing query strings in JavaScript:
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
console.log('Query variable %s not found', variable);
}
Now make a request to page.html?x=Hello:
console.log(getQueryVariable('x'));
function parseQuery(queryString) {
var query = {};
var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
}
return query;
}
Turns query string like hello=1&another=2 into object {hello: 1, another: 2}. From there, it's easy to extract the variable you need.
That said, it does not deal with array cases such as "hello=1&hello=2&hello=3". To work with this, you must check whether a property of the object you make exists before adding to it, and turn the value of it into an array, pushing any additional bits.
You can also use the excellent URI.js library by Rodney Rehm. Here's how:-
var qs = URI('www.mysite.com/default.aspx?dest=aboutus.aspx').query(true); // == { dest : 'aboutus.aspx' }
alert(qs.dest); // == aboutus.aspx
And to parse the query string of current page:-
var $_GET = URI(document.URL).query(true); // ala PHP
alert($_GET['dest']); // == aboutus.aspx
Me too! http://jsfiddle.net/drzaus/8EE8k/
(Note: without fancy nested or duplicate checking)
deparam = (function(d,x,params,p,i,j) {
return function (qs) {
// start bucket; can't cheat by setting it in scope declaration or it overwrites
params = {};
// remove preceding non-querystring, correct spaces, and split
qs = qs.substring(qs.indexOf('?')+1).replace(x,' ').split('&');
// march and parse
for (i = qs.length; i > 0;) {
p = qs[--i];
// allow equals in value
j = p.indexOf('=');
// what if no val?
if(j === -1) params[d(p)] = undefined;
else params[d(p.substring(0,j))] = d(p.substring(j+1));
}
return params;
};//-- fn deparam
})(decodeURIComponent, /\+/g);
And tests:
var tests = {};
tests["simple params"] = "ID=2&first=1&second=b";
tests["full url"] = "http://blah.com/?third=c&fourth=d&fifth=e";
tests['just ?'] = '?animal=bear&fruit=apple&building=Empire State Building&spaces=these+are+pluses';
tests['with equals'] = 'foo=bar&baz=quux&equals=with=extra=equals&grault=garply';
tests['no value'] = 'foo=bar&baz=&qux=quux';
tests['value omit'] = 'foo=bar&baz&qux=quux';
var $output = document.getElementById('output');
function output(msg) {
msg = Array.prototype.slice.call(arguments, 0).join("\n");
if($output) $output.innerHTML += "\n" + msg + "\n";
else console.log(msg);
}
var results = {}; // save results, so we can confirm we're not incorrectly referencing
$.each(tests, function(msg, test) {
var q = deparam(test);
results[msg] = q;
output(msg, test, JSON.stringify(q), $.param(q));
output('-------------------');
});
output('=== confirming results non-overwrite ===');
$.each(results, function(msg, result) {
output(msg, JSON.stringify(result));
output('-------------------');
});
Results in:
simple params
ID=2&first=1&second=b
{"second":"b","first":"1","ID":"2"}
second=b&first=1&ID=2
-------------------
full url
http://blah.com/?third=c&fourth=d&fifth=e
{"fifth":"e","fourth":"d","third":"c"}
fifth=e&fourth=d&third=c
-------------------
just ?
?animal=bear&fruit=apple&building=Empire State Building&spaces=these+are+pluses
{"spaces":"these are pluses","building":"Empire State Building","fruit":"apple","animal":"bear"}
spaces=these%20are%20pluses&building=Empire%20State%20Building&fruit=apple&animal=bear
-------------------
with equals
foo=bar&baz=quux&equals=with=extra=equals&grault=garply
{"grault":"garply","equals":"with=extra=equals","baz":"quux","foo":"bar"}
grault=garply&equals=with%3Dextra%3Dequals&baz=quux&foo=bar
-------------------
no value
foo=bar&baz=&qux=quux
{"qux":"quux","baz":"","foo":"bar"}
qux=quux&baz=&foo=bar
-------------------
value omit
foo=bar&baz&qux=quux
{"qux":"quux","foo":"bar"} <-- it's there, i swear!
qux=quux&baz=&foo=bar <-- ...see, jQuery found it
-------------------
Here's my version based loosely on Braceyard's version above but parsing into a 'dictionary' and support for search args without '='. In use it in my JQuery $(document).ready() function. The arguments are stored as key/value pairs in argsParsed, which you might want to save somewhere...
'use strict';
function parseQuery(search) {
var args = search.substring(1).split('&');
var argsParsed = {};
var i, arg, kvp, key, value;
for (i=0; i < args.length; i++) {
arg = args[i];
if (-1 === arg.indexOf('=')) {
argsParsed[decodeURIComponent(arg).trim()] = true;
}
else {
kvp = arg.split('=');
key = decodeURIComponent(kvp[0]).trim();
value = decodeURIComponent(kvp[1]).trim();
argsParsed[key] = value;
}
}
return argsParsed;
}
parseQuery(document.location.search);
Following on from my comment to the answer #bobby posted, here is the code I would use:
function parseQuery(str)
{
if(typeof str != "string" || str.length == 0) return {};
var s = str.split("&");
var s_length = s.length;
var bit, query = {}, first, second;
for(var i = 0; i < s_length; i++)
{
bit = s[i].split("=");
first = decodeURIComponent(bit[0]);
if(first.length == 0) continue;
second = decodeURIComponent(bit[1]);
if(typeof query[first] == "undefined") query[first] = second;
else if(query[first] instanceof Array) query[first].push(second);
else query[first] = [query[first], second];
}
return query;
}
This code takes in the querystring provided (as 'str') and returns an object. The string is split on all occurances of &, resulting in an array. the array is then travsersed and each item in it is split by "=". This results in sub arrays wherein the 0th element is the parameter and the 1st element is the value (or undefined if no = sign). These are mapped to object properties, so for example the string "hello=1&another=2&something" is turned into:
{
hello: "1",
another: "2",
something: undefined
}
In addition, this code notices repeating reoccurances such as "hello=1&hello=2" and converts the result into an array, eg:
{
hello: ["1", "2"]
}
You'll also notice it deals with cases in whih the = sign is not used. It also ignores if there is an equal sign straight after an & symbol.
A bit overkill for the original question, but a reusable solution if you ever need to work with querystrings in javascript :)
If you know that you will only have that one querystring variable you can simply do:
var dest = location.search.replace(/^.*?\=/, '');
The following function will parse the search string with a regular expression, cache the result and return the value of the requested variable:
window.getSearch = function(variable) {
var parsedSearch;
parsedSearch = window.parsedSearch || (function() {
var match, re, ret;
re = /\??(.*?)=([^\&]*)&?/gi;
ret = {};
while (match = re.exec(document.location.search)) {
ret[match[1]] = match[2];
}
return window.parsedSearch = ret;
})();
return parsedSearch[variable];
};
You can either call it once without any parameters and work with the window.parsedSearch object, or call getSearch subsequently.
I haven't fully tested this, the regular expression might still need some tweaking...
How about this?
function getQueryVar(varName){
// Grab and unescape the query string - appending an '&' keeps the RegExp simple
// for the sake of this example.
var queryStr = unescape(window.location.search) + '&';
// Dynamic replacement RegExp
var regex = new RegExp('.*?[&\\?]' + varName + '=(.*?)&.*');
// Apply RegExp to the query string
var val = queryStr.replace(regex, "$1");
// If the string is the same, we didn't find a match - return false
return val == queryStr ? false : val;
}
..then just call it with:
alert('Var "dest" = ' + getQueryVar('dest'));
Cheers
I wanted a simple function that took a URL as an input and returned a map of the query params.
If I were to improve this function, I would support the standard for array data in the URL, and or nested variables.
This should work back and for with the jQuery.param( qparams ) function.
function getQueryParams(url){
var qparams = {},
parts = (url||'').split('?'),
qparts, qpart,
i=0;
if(parts.length <= 1 ){
return qparams;
}else{
qparts = parts[1].split('&');
for(i in qparts){
qpart = qparts[i].split('=');
qparams[decodeURIComponent(qpart[0])] =
decodeURIComponent(qpart[1] || '');
}
}
return qparams;
};
I wanted to pick up specific links within a DOM element on a page, send those users to a redirect page on a timer and then pass them onto the original clicked URL. This is how I did it using regular javascript incorporating one of the methods above.
Page with links: Head
function replaceLinks() {
var content = document.getElementById('mainContent');
var nodes = content.getElementsByTagName('a');
for (var i = 0; i < document.getElementsByTagName('a').length; i++) {
{
href = nodes[i].href;
if (href.indexOf("thisurl.com") != -1) {
nodes[i].href="http://www.thisurl.com/redirect.aspx" + "?url=" + nodes[i];
nodes[i].target="_blank";
}
}
}
}
Body
<body onload="replaceLinks()">
Redirect page
Head
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
console.log('Query variable %s not found', variable);
}
function delayer(){
window.location = getQueryVariable('url')
}
Body
<body onload="setTimeout('delayer()', 1000)">

Matching exact string with JavaScript

How can I test if a RegEx matches a string exactly?
var r = /a/;
r.test("a"); // returns true
r.test("ba"); // returns true
testExact(r, "ba"); // should return false
testExact(r, "a"); // should return true
Either modify the pattern beforehand so that it only matches the entire string:
var r = /^a$/
or check afterward whether the pattern matched the whole string:
function matchExact(r, str) {
var match = str.match(r);
return match && str === match[0];
}
Write your regex differently:
var r = /^a$/;
r.test('a'); // true
r.test('ba'); // false
If you do not use any placeholders (as the "exactly" seems to imply), how about string comparison instead?
If you do use placeholders, ^ and $ match the beginning and the end of a string, respectively.
In case anyone receives an error like
Syntax Error: Invalid regular expression
by using the .match() function. You could always go back to the roots:
!!note this code is for matchin an exact string, if you want to search for an exact phrase in a string, you should filter it before hand
console.log("Exact data found: ", hasExactString("?hello", "?hello"))
console.log("Exact data found: ", hasExactString("?hello", "?helloBye"))
function hasExactString(data, searchTerm) {
console.log("search for ", searchTerm, " in ", data);
data = data.toLowerCase(); //if search term should be case insensitive
const searchExpressionLength = searchTerm.length;
const dataInputLength = data.length;
if (dataInputLength != searchExpressionLength) {
return false;
}
else {
//search letter by letter -back to the roots
for (var i = 0; i < searchExpressionLength; i++) {
if (data[i] != searchTerm[i]) {
return false;
}
}
return true;
}
}
...13 years late, but nonetheless^^
var data = {"values": [
{"name":0,"value":0.12791263050161572},
{"name":1,"value":0.13158780927382124}
]};
//JSON to string conversion
var a = JSON.stringify(data);
// replace all name with "x"- global matching
var t = a.replace(/name/g,"x");
// replace exactly the value rather than all values
var d = t.replace(/"value"/g, '"y"');
// String to JSON conversion
var data = JSON.parse(d);
Here's what is (IMO) by far the best solution in one line, per modern javascript standards:
const str1 = 'abc';
const str2 = 'abc';
return (str1 === str2); // true
const str1 = 'abcd';
const str2 = 'abc';
return (str1 === str2); // false
const str1 = 'abc';
const str2 = 'abcd';
return (str1 === str2); // false

Categories