Decoding URL parameters with JavaScript - javascript

This should be a simple task, but I can't seem to find a solution.
I have a basic string that is being passed through as a query string parameter like this one: This+is+a+message+with+spaces. I would like to decode that parameter using JavaScript to This is a message with spaces, but I cannot seem to get it to decode.
I've tried decodeURI('This+is+a+message+with+spaces') but the result still contains the + signs.

Yes it is true that decodeURIComponent function doesn't convert + to space. So you have to replace the + using replace function.
Ideally the below solution works.
var str_name = 'This+is+a+message+with+spaces';
decodeURIComponent((str_name + '').replace(/\+/g, '%20'));

Like it was pointed out already, decodeURI function doesn't convert + to space, but there are some things worth to realize here:
decodeURI is meant to be used for whole URI, i.e. it doesn't decode separators like ?, &, =, +, etc.
for decoding parameters decodeURIComponent should be used
(worth to have a look at: What is the difference between decodeURIComponent and decodeURI? )
string that you are trying to decode might actually contain + encoded as %2B, thus you should not replace + after the conversion since you might lost + signs that you actually want there, e.g. something?num=%2B632+905+123+4567 should become:
something?num=+632 905 123 4567
since you are probably going to extract the number: +632 905 123 4567
So the correct way to do this is:
var str = 'something?num=%2B632+905+123+4567';
decodeURIComponent( str.replace(/\+/g, '%20') );

The plus sign is not encoded/decoded. To see the decode function working, you need to pass a encoded URI first. Take a look:
encodeURI( "http://www.foo.com/bar?foo=foo bar jar" )
Will generate: http://www.foo.com/bar?foo=foo%20bar%20jar, i.e., the encoded URI.
decodeURI( "http://www.foo.com/bar?foo=foo%20bar%20jar" )
Will generate: http://www.foo.com/bar?foo=foo bar jar, i.e., the decoded URI.

The below code will decode and gives you the params in form of objects
export function getParamsFromUrl(url) {
url = decodeURI(url);
if (typeof url === 'string') {
let params = url.split('?');
let eachParamsArr = params[1].split('&');
let obj = {};
if (eachParamsArr && eachParamsArr.length) {
eachParamsArr.map(param => {
let keyValuePair = param.split('=')
let key = keyValuePair[0];
let value = keyValuePair[1];
obj[key] = value;
})
}
return obj;
}
}

I created my own string methods to support the needed encoding/decoding. These methods will handle the + encoding and decoding properly, allowing you to have plusses (+) in your string and still have the original spaces be encoded as +'s.
String.prototype.plusEncode = function() {
return encodeURIComponent(this).replace(/\%20/gm,"+");
}
String.prototype.plusDecode = function() {
return decodeURIComponent(this.replace(/\+/gm,"%20"));
}

Related

How to decode in JavaScript/Node.js a string of combined UTF16 and normal characters?

I have a huge JSON stringified into a string like this one:
"\\u007B\\u0022name\\u0022\\u003A\\u0022T\\u0065st\\u0022}"
I need to JSON.parse it to use as an object. Do you know any way to decode it?
I tried decodeURIComponent(), unescape(), different variants of .replace( /\\u/g, "\u" ) and I can not get it into the needed form.
You can convert UTF-16 to text using the following function:
function utf16ToText(s) {
return s.replace(/\\u[0-9a-fA-F]{4}/gi, match => {
return String.fromCharCode(parseInt(match.replace(/\\u/g, ""), 16));
});
}
Demo:
const r = utf16ToText("\\u007B\\u0022name\\u0022\\u003A\\u0022T\\u0065st\\u0022\\u007d");
console.log("As text: ", r);
const j = JSON.parse(r);
console.log("As JSON: ", j);
console.log("JSON Prop: ", j.name);
function utf16ToText(s) {
return s.replace(/\\u[0-9a-fA-F]{4}/gi, match => {
return String.fromCharCode(parseInt(match.replace(/\\u/g, ""), 16));
});
}
If your string is valid JSON, then you can use JSON.parse() to process the UTF16 for you. To make what you have valid JSON, you have to add double quotes to each end (inside the actual string) as all strings must be enclosed in double quotes in the JSON format. Here's an example:
let data = "\\u007B\\u0022name\\u0022\\u003A\\u0022T\\u0065st\\u0022\\u007d";
// to make this legal JSON so we can let the JSON parser parse it for us and
// handle the UTF16 for us, we need to put double quotes in the actual string at each end
// Then, it's legal JSON and we can parse it
let str = JSON.parse('"' + data + '"');
console.log(str);
console.log("type is", typeof str);
This gives you a result in string form:
{"name":"Test"}
This result is now legal JSON on its own. If you then wanted to parse that as JSON, could just call JSON.parse() on it again to turn it into an actual Javascript object:
let data = "\\u007B\\u0022name\\u0022\\u003A\\u0022T\\u0065st\\u0022\\u007d";
let str = JSON.parse('"' + data + '"'); // decoded string here
// now take the string and actually parse it into a Javascript object
let obj = JSON.parse(str);
console.log(obj); // Javascript object here
console.log("type is", typeof obj);
This gives you a resulting live Javascript object:
{name:"Test"}
The first call to JSON.parse() just takes your JSON string and decodes it into a Javascript string. Since that Javascript string is now also legal JSON for an object definition, you can call JSON.parse() on it again to turn it into a Javascript object.
Thank you for your input. Because of that, I got the solution:
let a = "\\u007B\\u0022name\\u0022\\u003A\\u0022T\\u0065st\\u0022}" original string
let b = '"' + a + '"' adding " in order to make a valid stringified JSON
let c = JSON.parse(b) that will produce a partially decoded string (partially because some of the \uXXXX characters can stay in the string)
let solution = JSON.parse(c) that will create an object with all the characters decoded
Big thanks to #jfriend00

Raw String to normal string javascript

Normal String assignment:
var str1 = "\320";
console.log(str1); // "Ð"
Raw String assignment:
var str2 = String.raw`\320`;
console.log(str2); // "\320"
In raw string, the backslashes are not interpreted. I need to interpret them so that "\320" will become "Ð". Should I have to convert the raw string to normal String. If so, How? If not so, what else should I do and how do I do?
The thing is, this code is octal, and since these are mapped with linguistic symbols, javascript interpretes it when defining new string.
what you can do is make a map of all the symbols you require with their key as actual string and value as actual symbol.
for ex -
var map = {
"\\320": "\320"
}
console.log(map);
now you can search you text in the map and get the required value.
var str2 = String.raw`\320`;
var s = map[str2];
console.log(s);
to make the map, try this -
visit this site - https://brajeshwar.github.io/entities/
and run this code on console
// for latin
var tbody = document.getElementById("latin");
var trs = tbody.children;
var map = {};
for(i=1;i<trs.length;i++) {
console.log(trs[i].children[6].innerText);
key = trs[i].children[6].innerText;
value = trs[i].children[1].innerText;
map[key] = value;
}
now console map, stringify it, and paste the string in your code and parse it.
I have done this only for latin, similarly do this for other elements also.
Question is a couple of months old, but I think this answer is your best bet, yet. Transforming escape sequences from raw strings is very much doable with ES6 String.fromcodepoint(<hex-value>). I'm in the middle of writing an NPM package which deals with this exact scenario.
First, you need a regular expression which matches all escape sequences in your string. I've used this as a reference for all the different ones. (I use a raw string for this to avoid spamming backslashes)
let [single, ...hex] = String.raw`
\\[bfnrtv0'"\\]
\\x[a-fA-F0-9]{2}
(\\u[a-fA-F0-9]{4}){1,}
\\u\{([0-9a-fA-F]{1,})\}`
.split("\n").slice(1).map(cur => cur.trim());
let escapes = new RegExp(`(${[single].concat(hex).join("|")})`, "gm"),
// We need these for later when differentiating how we convert the different escapes.
uniES6 = new RegExp(`${hex.pop()}`);
single = new RegExp(`${single}`);
Now you can match all the escapes; reserved single characters, extended ASCII range, ES6 "Astral" unicode hexadecimals and surrogate pairs. (except octals because they're deprecated, but you can always add it back). The next step is writing a function which can replace the code points with the corresponding symbols. First a switch-like function for singles:
const singleEscape = seq =>
(() => ({
"\\b" : "\b",
"\\f" : "\f",
"\\n" : "\n",
"\\r" : "\r",
"\\t" : "\t",
"\\v" : "\v",
"\\0" : "\0",
"\\'" : "\'",
"\\\"" : "\"",
"\\\\" : "\\"
}[seq]))();
Then we can rely on ES6 fromcodepoint to deal with the rest which are all hexadecimals.
const convertEscape = seq => {
if (single.test(seq))
return singleEscape(seq);
else if (uniES6.test(seq))
return String.fromCodePoint(`0x${seq.split("").slice(3, -1).join("")}`);
else
return String.fromCodePoint.apply(
String, seq.split("\\").slice(1).map(pt => `0x${pt.substr(1)}`)
);
}
Lastly, we tie it all together with a tagged template literal function named normal. I do not know why you need a raw string, but here you can have access to the raw string and put any additional logic while still resulting in a string where escape sequences are properly parsed.
const normal = (strings, ...values) => strings.raw
.reduce((acc, cur, i) => acc += (values[i-1] || "") + cur, "")
.replace(escapes, match => convertEscape(match));

want to split a string after a certain word?

Here is my code:
var url="https://muijal-ip-dev-ed.my.salesforce.com/apexpages/setup/viewApexPage.apexp?id=066415642TPaE";
In this string i need only
url="https://muijal-ip-dev-ed.my.salesforce.com/"
i need string upto "com/" rest of the string should be removed.
In modern browsers you can use URL()
var url=new URL("https://muijal-ip-dev-ed.my.salesforce.com/apexpages/setup/viewApexPage.apexp?id=066415642TPaE");
console.log(url.origin)
For unsupported browsers use regex
use javascript split
url = url.split(".com");
url = url[0] + ".com";
That should leave you with the wanted string if the Url is well formed.
You can use locate then substr like this:
var url = url.substr(0, url.locate(".com"));
locate returns you the index of the string searched for and then substr will cut from the beginning until that index~
Substring function should handle that nicely:
function clipUrl(str, to, include) {
if (include === void 0) {
include = false;
}
return str.substr(0, str.indexOf(to) + (include ? to.length : 0));
}
console.log(clipUrl("https://muijal-ip-dev-ed.my.salesforce.com/apexpages/setup/viewApexPage.apexp?id=066415642TPaE", ".com", true));
If the URL API (as suggested by another answer) isn't available you can reliably use properties of the HTMLAnchorElement interface as a workaround if you want to avoid using regular expressions.
var a = document.createElement('a');
a.href = 'https://muijal-ip-dev-ed.my.salesforce.com/apexpages/setup/viewApexPage.apexp?id=066415642TPaE';
console.log(a.protocol + '//' + a.hostname);

With JavaScript, I need help concatenating a variable into a regular expression

I'm writing a JavaScript function to extract a segment out of a URL that appears to the right of a designated segment.
For instance, if this is my URL ...
mysite.com/cat/12/dog/34?test=123
... I would like to be able to pass 'cat' to the function and get 12, and later pass 'dog' to the function and have it return 34. I found this answer on StackOverflow to extract the URL segment, but it uses a string literal. And I'm having difficulty concatenating a passed in value.
jQuery to parse our a part of a url path
Here is my code. In this, rather than hard coding 'cat' into the pattern match, I would like to pass 'cat' into the segmentName parameter and have the regular expression match on that.
var url = "www.mysite.com/cat/12/dog/34?test=123";
alert(getNextSegmentAfterSegmentName(url, 'cat'));
function getNextSegmentAfterSegmentName(currentPath, segmentName) {
var nextSegment = "";
segmentName = segmentName.toLowerCase();
//var currentPath = window.location.pathname.toLowerCase();
if (currentPath.indexOf(segmentName) >= 0) {
var path = currentPath.split('?')[0]; // Strip querystring
// How do I concatenate segmentName into this?
var matches = path.match(/\/cat\/([^\/]+)/);
if (matches) {
nextSegment = matches[1];
}
}
return nextSegment;
}
Here is a jsfiddle example:
http://jsfiddle.net/Stormjack/2Ebsv/
Thanks for your help!
You need to create a RegExp object if you want to create regex using some string variable:
path.match(new RegExp("\/" + segmentName + "\/([^\/]+)"));

How do I extract data from this URL using javascript?

I need to build a string from the data contained in this url using javascript/jQuery:
http://www.example.com/members/admin/projects/?projectid=41
The string returned should look as follows:
/ajax/projects.php?projectid=41
Obviously if there is no query string present, the method should still return a string of the same format minus the query string. e.g.
http://www.example.com/members/admin/messages/
should return...
/ajax/messages.php
I've made numerous attempts, all met without success due to my poor grasp of regular expressions, and it feels as though the ore I rad on the subject the more I am confusing myself.
If someone could help it would be greatly appreciated.
EDIT: The 'admin' portion of the url is a users 'username' and could be anything.
Here's a function that will take your URL and return a new one according to the rules you've listed above:
function processURL(url) {
var base = "", query = "";
var matches = url.match(/([^\/\?]+)(\/$|$|\?|\/\?)/);
if (matches) {
base = matches[1];
matches = url.match(/\?[^\?]+$/);
if (matches) {
query = matches[0];
}
}
return("/ajax/" + base + ".php" + query);
}
And, a test app that shows it working on a bunch of URLs: http://jsfiddle.net/jfriend00/UbDfn/
Input URLs:
var urls = [
"http://www.example.com/members/admin/projects/?projectid=41",
"http://www.example.com/members/bob/messages/",
"http://www.example.com/members/jill/projects/",
"http://www.example.com/members/alice/projects?testid=99",
"http://www.example.com/members/admin/projects/?testid=99"
];
Output results:
/ajax/projects.php?projectid=41
/ajax/messages.php
/ajax/projects.php
/ajax/projects.php?testid=99
/ajax/projects.php?testid=99
To explain, the first regular expression looks for:
a slash
followed by one or more characters that is not a slash and not a question mark
followed by one of the four sequences
/$ a slash at the end of the string
$ end of the string
? a question mark
/? a slash followed by a question mark
The point of this regex is to get the last segment of the path that comes before either the end of the string or the query parameters and it's tolerant of whether the last trailing slash is there or not and whether there are any query parameters.
I know exactly what you are trying to do. In order to do it your way just split your string on question mark and then use last item form your array.
var data = your_url.split('?');
var newUrl = '/ajax/projects.php' + (data.length > 1 ? data[length-1] : "");
and you will have your url.
But what you can do is execute same url using your Script just add one parameter IsAjax=true and then check it in codebehind and execute your ajax logic.
e.g.
$('#somelink').onclick(function(){
$.ajax({ url: $(this).href, data { IsAjax: true } .... }
});
Using this way you will have more robust app.
I'll assume that by
http://www.example.com/members/admin/messages/
should return...
/ajax/members.php
you meant - should return...
/ajax/messages.php
If that is the case try
var query = url.split('?');
var paths = query[0].split('/');
var path = paths.pop();
if (path == '') //when there is trailing slash
path = paths.pop();
if (query.length == 1) //no query string
newurl = '/ajax/' + path + '.php';
else //query string
newurl = '/ajax/' + path + '.php?' + query[1];
I'm sure it can be made simpler and better, but that might give you a start.
var str = "http://www.example.com/members/admin/projects/?projectid=41";
var newStr = "/ajax/" + str.split("/").slice(-2).join(".php");
console.log(newStr);

Categories

Resources