I am trying to replace values in a string with the comparable jSON property in an object.
var value = "/sessions/:sessionId/events/:id";
var result = replace(value, { sessionId : 1 , id : 23 });
// result : "/sessions/1/events/23"
console.log(result);
Is it possible with JavaScript (I'm sure it is)? Not sure about the most efficient way to do this and how to handle it when all the values inside the template string are not matched.
Thanks in advance.
Update (Solution)
var url = function (template, parameters) {
var extra = [];
for (param in parameters) {
if (value.indexOf(param) < 0) {
extra.push(param + '=' + parameters[param]);
}
}
var result = template.replace(/:(\w+)/g, function (substring, match) {
var routeValue = parameters[match];
if (!routeValue) {
throw "missing route value for " + match + ' in "' + template +'"';
}
return routeValue;
});
if (result.indexOf("/:") > 0) {
throw "not all route values were matched";
}
return (extra.length === 0) ? result : result + "?" + extra.join("&");
};
var value = "/sessions/:sessionId/events/:id";
var data = {
sessionId: 1,
id: 23,
term: "butter"
};
// result : /sessions/1/events/21?term=butter
console.log(url(value, data));
A regex would work just fine here.
var value = "/sessions/:sessionId/events/:id";
var obj = { sessionId : 1 , id : 23 };
var result = value.replace(/:(\w+)(\/|\b)/g, function(substring, match, nextMatch){
return obj[match] + nextMatch;
});
Assuming you have the following javascript object:
var myObject = { sessionId : 1 , id : 23 };
you can loop each property and do a replace on the original string...
var value = "/sessions/:sessionId/events/:id";
for(var item in myObject){
value = value.replace(item, myObject[item]);
}
//value = "/sessions/:1/events/:23"
Here is a working example
It is not clear if you want to keep the : characters or not. If not, then you can just include that in your replace function:
value = value.replace(':' + item, myObject[item]);
Checking for missing parameters
If you have any extra values in your object that do not exist in your input string, then they will not have any effect. If however, you want to take action if one of the items is not found in the original string, then you can do a check in the loop:
var noMatch = false;
for(var item in myObject){
if(value.indexOf(item) < 0){
noMatch = true;
}
value = value.replace(item, myObject[item]);
}
if(noMatch){
//something is wrong!
}
Dealing with JSON
If you do actually have a JSON string to begin with, you can convert that to an object with the following:
var jsonString = '{"sessionId": 1, "id": 23}';
var myObject = JSON.parse(jsonString);
here is another way of doing it.
http://jsfiddle.net/rayweb_on/suHej/
var value = "/sessions/:sessionId/events/:id";
var source = { sessionId : 1 , id : 23 };
var result = value.replace(":sessionId",source.sessionId);
var result = result.replace(":id",source.id);
console.log(result);
Related
I have a JSON array returned via ajax that looks like:
"stuff": [["2","66%"], ["3","42%"],...
Problem
I want to match the zeroth index of each element in this array to a variable outside of the loop and if it matches, I want to return the percentage next to it.
I don't know the syntax in jQuery for this. Please have a look at my code below and see if that's correct or not:
var percentage = 0;
var stuffarr = jsonobj['stuff'];
var stuffID = jsonobj['stuff_id']
if (!stuffID || 0 === stuffID.length){
$("#stuff-element").html("--");
}
else {
var percentage = $.each(stuffarr, function (index, value) {
if(value[0] == stuffID)
return value[1]
});
}
Firstly, a bit of terminology. The data structure you have is an Object which holds several properties. It has nothing to do with JSON after it has been deserialised.
With regard to your issue, there's no jQuery required as you can use find() to find the item in the array by the stuffID variable's value. Try this:
var obj = {
"stuff": [
["2", "66%"],
["3", "42%"]
],
"stuff_id": "3"
}
var percentage = 0;
var stuffArr = obj['stuff'];
var stuffId = obj['stuff_id']
if (!stuffId || 0 === stuffId.length) {
$("#stuff-element").html("--");
} else {
percentage = stuffArr.find(function(el) {
return el[0] == stuffId;
})[1];
}
console.log(percentage);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
try this
var percentage = stuffarr.find(function (value) {
if(value[0] == stuffID)
return value[1];
})[1];
The return statement you used returns the result of the function(..) inside the .each(..) function and is not the return value of the .each(..) function.
the valid return value is boolean which 'tells' the .each(..) function whether it should continue or not. instead use the following syntax:
var ret = '';
$(arr).each(function () {
var curr = $(this);
//console.log(curr);
if(curr[0] == stuffID){
//console.log('>>found: ' + curr[1]);
ret = curr[1];
//if found -> break loop
return false;
}
});
comment: you should consider instead of using an inner array data structure use an object, this is a more 'correct' data structure:
// "stuff": [{"id":"2","percent":"66%"}, {"id":"3","percent":"42%"},...
var ret = '';
$(arr).each(function () {
var curr = this;
//console.log(curr.id);
if(curr.id == stuffID){
//console.log('>>found: ' + curr.percent);
ret = curr.percent;
//if found -> break loop
return false;
}
});
#LiverpoolOwen approach is clean and nice, and if you want to use it combining with the object approach do this:
arr.find(function (value) {
if(value.id == stuffID)
return value;
}).percent;
In the below code Im not getting the right result. How can I can do pattern match in javascript?
function getPathValue(url, input) {
console.log("this is path key :"+input);
url = url.replace(/%7C/g, '|');
var inputarr = input.split("|");
if (inputarr.length > 1)
input = '\\b' + inputarr[0] + '\n|' + inputarr[1] + '\\b';
else
input = '\\b' + input + '\\b';
var field = url.search(input);
var slash1 = url.indexOf("/", field);
var slash2 = url.indexOf("/", slash1 + 1);
if (slash2 == -1)
slash2 = url.indexOf("?");
if (slash2 == -1)
slash2 = url.length;
console.log("this is path param value :"+url.substring(slash1 + 1, slash2));
return url.substring(slash1 + 1, slash2);
}
getPathValue("http://localhost/responsePath/mountainwithpassid|accesscode/100/mountainwithpassid|passid/1","mountainwithpassid|passid")
Im getting the below output
If I pass mountainwithpassid|accesscode as input Im getting output as
100. Same way if I pass
key :mountainwithpassid|passid value :100 // Expected output 1
If your intention is to simply retrieve the value in the path that follows the input (contained within '/') then you can achieve this with a simpler regular expression. First you will need a method to escape your input string since it contains a pipe character '|' which is translated as OR in regex.
You can use this (taken from https://stackoverflow.com/a/3561711):
RegExp.escape= function(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};
Then your getPathValue function can look something like:
function getPathValue(url, input) {
var pathValue = null;
var escapedInput = RegExp.escape(input);
// The RegExp below extracts the value that follows the input and
// is contained within '/' characters (the last '/' is optional)
var pathValueRegExp = new RegExp(".*" + escapedInput + "/([^/]+)/?.*", 'g');
if (pathValueRegExp.test(url)) {
pathValue = url.replace(pathValueRegExp, '$1');
}
return pathValue;
}
You will also need to think about how you handle errors - in the example a null value is returned if no match is found.
I'm trying to understand the question. Given a URL of:
"http://localhost/responsePath/mountainwithpassid|accesscode/100/mountainwithpassid|passid/1"
and an argument of:
"mountainwithpassid|passid"
you expect a return value of:
"1"
An argument of
"mountainwithpassid|accesscode"
should return:
"100"
Is that correct? If so (and I'm not certain it is) then the following may suit:
function getPathValue(url, s) {
var x = url.indexOf(s);
if (x != -1) {
return url.substr(x).split('/')[1];
}
}
var url = "http://localhost/responsePath/mountainwithpassid|accesscode/100/mountainwithpassid|passid/1";
var x = "mountainwithpassid|passid";
var y = "mountainwithpassid|accesscode";
console.log(getPathValue(url, x)); // 1
console.log(getPathValue(url, y)); // 100
I'm writing a program that takes in some data from a file (in this case, a list of IDs).
This program then takes the IDs, interfaces with a weather server, grabs the information the server kicks back, and parses it.
It then sorts the data in order of name by city, and pushes it into an array.
I'm trying to get it printed out, but when I print the array, I keep getting the following output:
[ { string: 'Dallas, TX : 91' },
{ string: 'Houston, TX : 86' },
{ string: 'Houston, TX : 86' },
{ string: 'Jacksonville, FL : 83' },
{ string: 'Laguna Hills, CA : 67' },
{ string: 'New York, NY : 91' },
{ string: 'Seattle, WA : 62' } ]
Naturally, I anticipate having the square brackets included, and the commas as well. However, why is it printing out the "string:" and curly braces?
Here is my source:
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var lineReader = require('line-reader');
var cityList = [];
var numItems = 0;
var needToPrint = 0;
lineReader.eachLine('IDList.txt', function(line, last) {
numItems++;
getResponse(line, textParse);
});
var getResponse = function(id, callback){
var request = new XMLHttpRequest;
request.open("GET", "http://weather.yahooapis.com/forecastrss?w=" + id +"&u=f");
request.onreadystatechange = function(){
if(request.readyState === 4 && request.status === 200){
var type = request.getResponseHeader("Content-Type");
if(type.indexOf("xml") !== -1 && request.responseXML)
callback(request.responseXML);
else if(type === "application/json")
callback(JSON.parse(request.responseText));
else
callback(request.responseText);
}
};
request.send(id);
}
var textParse = function (input)
{
var index = input.indexOf("city=\"") + "city=\"".length;
var endIndex = input.indexOf("\" region=\"");
var city = input.substring(index, endIndex);
index = input.indexOf("region=\"") + "region=\"".length;
var state = input.substring(index, index + 2);
index = input.indexOf("temp=\"") + "temp=\"".length;
endIndex = input.indexOf("\"", index);
var temp = input.substring(index, endIndex);
var obj = new location(city, state, temp);
cityList.push(obj);
cityList.sort(sortFunc);
needToPrint++;
if(numItems === needToPrint)
printData(cityList);
}
var location = function (city, state, currentTemp)
{
this.string = city + ", " + state + " : " + currentTemp;
};
var sortFunc = function(input1, input2)
{
if (input1.string < input2.string) //sort string ascending
return -1
if (input1.string > input2.string)
return 1
return 0 //default return value (no sorting)
}
var printData = function(objectList){
console.log(objectList);
}
You're creating a location object:
var obj = new location(city, state, temp);
In that object, you create a string property:
this.string = city + ", " + state + " : " + currentTemp;
If what you want is a simple array of strings, change textParse to do this:
cityList.push(city + ", " + state + " : " + currentTemp);
(instead of pushing a location object)
This would require you to rewrite the sort function too.
It looks like you didn't write that code, otherwise you would understand it. Maybe what you're missing is that objectList is an array of objects. You can access your data by array index, then object property (in this case, string). For example, try this in printData:
console.log(objectList[1].string); // 'Houston, TX : 86'
For further info on how to traverse your data, see Access / process (nested) objects, arrays or JSON
It looks like you're pushing Javascript objects into the cityList array, so when you call printData(cityList), you're logging an array object, not a string. So, the console spits out JSON. If you want raw text, you need to build a string.
I cannot find out the regex to get param value from the part of query string:
I need to send parameter name to a method and get parameter value as result for string like
"p=1&qp=10".
I came up with the following:
function getParamValue(name) {
var regex_str = "[&]" + name + "=([^&]*)";
var regex = new RegExp(regex_str);
var results = regex.exec(my_query_string);
// check if result found and return results[1]
}
My regex_str now doesn't work if name = 'p'. if I change regex_str to
var regex_str = name + "=([^&]*)";
it can return value of param 'qp' for param name = 'p'
Can you help me with regex to search the beginning of param name from right after '&' OR from the beginning of a string?
This might work, depending on if you have separated the parameter part.
var regex_str = "(?:^|\&)" + name + "=([^&]*)";
or
var regex_str = "(?:\&|\?)" + name + "=([^&]*)";
Looks like split will work better here:
var paramsMap = {};
var params = string.split("&");
for (var i = 0; i < params.length; ++i) {
var keyValue = params[i].split("=", 2);
paramsMap[keyValue[0]] = keyValue[1];
}
If you desperately want to use a regex, you need to use the g flag and the exec method. Something along the lines of
var regex = /([^=]+)=([^&]+)&?/g;
var paramsMap = {};
while (true) {
var match = regex.exec(input);
if (!match)
break;
paramsMap[match[1]] = match[2];
}
Please note that since the regex object becomes stateful, you either need to reset its lastIndex property before running another extraction loop or use a new RegExp instance.
Change your regex string to the following:
//pass the query string and the name of the parameter's value you want to retrieve
function getParamValue(my_query_string , name)
{
var regex_str = "(?:^|\&)" + name + "\=([^&]*)";
var regex = new RegExp(regex_str);
var results = regex.exec(my_query_string);
try
{
if(results[1] != '')
{
return results[1];
}
}
catch(err){};
return false;
}
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)">