How to get the domain name without subdomains?
e.g. if the url is "http://one.two.roothost.co.uk/page.html" how to get "roothost.co.uk"?
Following is a solution to extract a domain name without any subdomains. This solution doesn't make any assumptions about the URL format, so it should work for any URL. Since some domain names have one suffix (.com), and some have two or more (.co.uk), to get an accurate result in all cases, we need to parse the hostname using the Public Suffix List, which contains a list of all public domain name suffixes.
Solution
First, include the public suffix list js api in a script tag in your HTML, then in JavaScript to get the hostname you can call:
var parsed = psl.parse('one.two.roothost.co.uk');
console.log(parsed.domain);
...which will return "roothost.co.uk". To get the name from the current page, you can use location.hostname instead of a static string:
var parsed = psl.parse(location.hostname);
console.log(parsed.domain);
Finally, if you need to parse a domain name directly out of a full URL string, you can use the following:
var url = "http://one.two.roothost.co.uk/page.html";
url = url.split("/")[2]; // Get the hostname
var parsed = psl.parse(url); // Parse the domain
document.getElementById("output").textContent = parsed.domain;
JSFiddle Example (it includes the entire minified library in the jsFiddle, so scroll down!): https://jsfiddle.net/6aqdbL71/2/
What about this?
function getCanonicalHost(hostname) {
const MAX_TLD_LENGTH = 3;
function isNotTLD(_) { return _.length > MAX_TLD_LENGTH; };
hostname = hostname.split('.');
hostname = hostname.slice(Math.max(0, hostname.findLastIndex(isNotTLD)));
hostname = hostname.join('.');
return hostname;
}
console.log(getCanonicalHost('mail.google.com'));
console.log(getCanonicalHost('some.google.com.ar'));
console.log(getCanonicalHost('some.another.google.com.ar'));
console.log(getCanonicalHost('foo.bar.google.com'));
console.log(getCanonicalHost('foo.bar.google.com.ar'));
console.log(getCanonicalHost('bar.google.ar'));
Its works since https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_domain_name say:
TLDs can contain special as well as latin characters. A TLD's maximum length is 63 characters, although most are around 2–3.
In https://data.iana.org/TLD/tlds-alpha-by-domain.txt are 1481 TLD, 466 of this has length around 2–3 and the most used TLD no has more than 3.
If you need a solution that works with all TLDS, here is a more complex aproach:
function getCanonicalHost(hostname) {
return getCanonicalHost.tlds.then(function(tlds) {
function isNotTLD(_) { return tlds.indexOf(_) === -1; };
hostname = hostname.toLowerCase();
hostname = hostname.split('.');
hostname = hostname.slice(Math.max(0, hostname.findLastIndex(isNotTLD)));
hostname = hostname.join('.');
return hostname;
});
}
getCanonicalHost.tlds = new Promise(function(res, rej) {
const TLD_LIST_URL= 'https://data.iana.org/TLD/tlds-alpha-by-domain.txt';
const xhr = new XMLHttpRequest();
xhr.addEventListener('error', rej);
xhr.addEventListener('load', function() {
const MAX_TLD_LENGTH = 63;
var tlds = xhr.responseText.split('\n');
tlds = tlds.map(function(_) { return _.trim().toLowerCase(); });
tlds = tlds.filter(Boolean);
tlds = tlds.filter(function(_) { return _.length < MAX_TLD_LENGTH; });
res(tlds);
});
xhr.open('GET', TLD_LIST_URL);
xhr.send();
})
getCanonicalHost('mail.google.com').then(console.log);
getCanonicalHost('some.google.com.ar').then(console.log);
getCanonicalHost('some.another.google.com.ar').then(console.log);
getCanonicalHost('foo.bar.google.com').then(console.log);
getCanonicalHost('foo.bar.google.com.ar').then(console.log);
getCanonicalHost('bar.google.ar').then(console.log);
You can use parse-domain to do the heavy lifting for you. This package considers the public suffix list and returns an easy to work with object breaking up the domain.
Here is an example from their readme:
npm install parse-domain
import { parseDomain, ParseResultType } from 'parse-domain';
const parseResult = parseDomain(
// should be a string with basic latin characters only. more details in the readme
'www.some.example.co.uk',
);
// check if the domain is listed in the public suffix list
if (parseResult.type === ParseResultType.Listed) {
const { subDomains, domain, topLevelDomains } = parseResult;
console.log(subDomains); // ["www", "some"]
console.log(domain); // "example"
console.log(topLevelDomains); // ["co", "uk"]
} else {
// more about other parseResult types in the readme
}
This works for me:
const firstTLDs = "ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|be|bf|bg|bh|bi|bj|bm|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|cl|cm|cn|co|cr|cu|cv|cw|cx|cz|de|dj|dk|dm|do|dz|ec|ee|eg|es|et|eu|fi|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jo|jp|kg|ki|km|kn|kp|kr|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|na|nc|ne|nf|ng|nl|no|nr|nu|nz|om|pa|pe|pf|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|yt".split('|');
const secondTLDs = "com|edu|gov|net|mil|org|nom|sch|caa|res|off|gob|int|tur|ip6|uri|urn|asn|act|nsw|qld|tas|vic|pro|biz|adm|adv|agr|arq|art|ato|bio|bmd|cim|cng|cnt|ecn|eco|emp|eng|esp|etc|eti|far|fnd|fot|fst|g12|ggf|imb|ind|inf|jor|jus|leg|lel|mat|med|mus|not|ntr|odo|ppg|psc|psi|qsl|rec|slg|srv|teo|tmp|trd|vet|zlg|web|ltd|sld|pol|fin|k12|lib|pri|aip|fie|eun|sci|prd|cci|pvt|mod|idv|rel|sex|gen|nic|abr|bas|cal|cam|emr|fvg|laz|lig|lom|mar|mol|pmn|pug|sar|sic|taa|tos|umb|vao|vda|ven|mie|北海道|和歌山|神奈川|鹿児島|ass|rep|tra|per|ngo|soc|grp|plc|its|air|and|bus|can|ddr|jfk|mad|nrw|nyc|ski|spy|tcm|ulm|usa|war|fhs|vgs|dep|eid|fet|fla|flå|gol|hof|hol|sel|vik|cri|iwi|ing|abo|fam|gok|gon|gop|gos|aid|atm|gsm|sos|elk|waw|est|aca|bar|cpa|jur|law|sec|plo|www|bir|cbg|jar|khv|msk|nov|nsk|ptz|rnd|spb|stv|tom|tsk|udm|vrn|cmw|kms|nkz|snz|pub|fhv|red|ens|nat|rns|rnu|bbs|tel|bel|kep|nhs|dni|fed|isa|nsn|gub|e12|tec|орг|обр|упр|alt|nis|jpn|mex|ath|iki|nid|gda|inc".split('|');
const knownSubdomains = "www|studio|mail|remote|blog|webmail|server|ns1|ns2|smtp|secure|vpn|m|shop|ftp|mail2|test|portal|ns|ww1|host|support|dev|web|bbs|ww42|squatter|mx|email|1|mail1|2|forum|owa|www2|gw|admin|store|mx1|cdn|api|exchange|app|gov|2tty|vps|govyty|hgfgdf|news|1rer|lkjkui";
function removeSubdomain(s) {
const knownSubdomainsRegExp = new RegExp(`^(${knownSubdomains})\.`, 'i');
s = s.replace(knownSubdomainsRegExp, '');
const parts = s.split('.');
while (parts.length > 3) {
parts.shift();
}
if (parts.length === 3 && ((parts[1].length > 2 && parts[2].length > 2) || (secondTLDs.indexOf(parts[1]) === -1) && firstTLDs.indexOf(parts[2]) === -1)) {
parts.shift();
}
return parts.join('.');
};
var tests = {
'www.sidanmor.com': 'sidanmor.com',
'exemple.com': 'exemple.com',
'argos.co.uk': 'argos.co.uk',
'www.civilwar.museum': 'civilwar.museum',
'www.sub.civilwar.museum': 'civilwar.museum',
'www.xxx.sub.civilwar.museum': 'civilwar.museum',
'www.exemple.com': 'exemple.com',
'main.testsite.com': 'testsite.com',
'www.ex-emple.com.ar': 'ex-emple.com.ar',
'main.test-site.co.uk': 'test-site.co.uk',
'en.tour.mysite.nl': 'tour.mysite.nl',
'www.one.lv': 'one.lv',
'www.onfdsadfsafde.lv': 'onfdsadfsafde.lv',
'aaa.onfdsadfsafde.aa': 'onfdsadfsafde.aa',
};
const firstTLDs = "ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|be|bf|bg|bh|bi|bj|bm|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|cl|cm|cn|co|cr|cu|cv|cw|cx|cz|de|dj|dk|dm|do|dz|ec|ee|eg|es|et|eu|fi|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jo|jp|kg|ki|km|kn|kp|kr|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|na|nc|ne|nf|ng|nl|no|nr|nu|nz|om|pa|pe|pf|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|yt".split('|');
const secondTLDs = "com|edu|gov|net|mil|org|nom|sch|caa|res|off|gob|int|tur|ip6|uri|urn|asn|act|nsw|qld|tas|vic|pro|biz|adm|adv|agr|arq|art|ato|bio|bmd|cim|cng|cnt|ecn|eco|emp|eng|esp|etc|eti|far|fnd|fot|fst|g12|ggf|imb|ind|inf|jor|jus|leg|lel|mat|med|mus|not|ntr|odo|ppg|psc|psi|qsl|rec|slg|srv|teo|tmp|trd|vet|zlg|web|ltd|sld|pol|fin|k12|lib|pri|aip|fie|eun|sci|prd|cci|pvt|mod|idv|rel|sex|gen|nic|abr|bas|cal|cam|emr|fvg|laz|lig|lom|mar|mol|pmn|pug|sar|sic|taa|tos|umb|vao|vda|ven|mie|北海道|和歌山|神奈川|鹿児島|ass|rep|tra|per|ngo|soc|grp|plc|its|air|and|bus|can|ddr|jfk|mad|nrw|nyc|ski|spy|tcm|ulm|usa|war|fhs|vgs|dep|eid|fet|fla|flå|gol|hof|hol|sel|vik|cri|iwi|ing|abo|fam|gok|gon|gop|gos|aid|atm|gsm|sos|elk|waw|est|aca|bar|cpa|jur|law|sec|plo|www|bir|cbg|jar|khv|msk|nov|nsk|ptz|rnd|spb|stv|tom|tsk|udm|vrn|cmw|kms|nkz|snz|pub|fhv|red|ens|nat|rns|rnu|bbs|tel|bel|kep|nhs|dni|fed|isa|nsn|gub|e12|tec|орг|обр|упр|alt|nis|jpn|mex|ath|iki|nid|gda|inc".split('|');
const knownSubdomains = "www|studio|mail|remote|blog|webmail|server|ns1|ns2|smtp|secure|vpn|m|shop|ftp|mail2|test|portal|ns|ww1|host|support|dev|web|bbs|ww42|squatter|mx|email|1|mail1|2|forum|owa|www2|gw|admin|store|mx1|cdn|api|exchange|app|gov|2tty|vps|govyty|hgfgdf|news|1rer|lkjkui";
function removeSubdomain(s) {
const knownSubdomainsRegExp = new RegExp(`^(${knownSubdomains})\.`, 'i');
s = s.replace(knownSubdomainsRegExp, '');
const parts = s.split('.');
while (parts.length > 3) {
parts.shift();
}
if (parts.length === 3 && ((parts[1].length > 2 && parts[2].length > 2) || (secondTLDs.indexOf(parts[1]) === -1) && firstTLDs.indexOf(parts[2]) === -1)) {
parts.shift();
}
return parts.join('.');
};
for (var test in tests) {
if (tests.hasOwnProperty(test)) {
var t = test;
var e = tests[test];
var r = removeSubdomain(test);
var s = e === r;
if (s) {
console.log('OK: "' + t + '" should be "' + e + '" and it is really "' + r + '"');
} else {
console.log('Fail: "' + t + '" should be "' + e + '" but it is NOT "' + r + '"');
}
}
}
Referance:
psl.min.js file
Maximillian Laumeister Answer to this question
The most popular subdomains on the internet
Simplest solution:
var domain='https://'+window.location.hostname.split('.')[window.location.hostname.split('.').length-2]+'.'+window.location.hostname.split('.')[window.location.hostname.split('.').length-1];
alert(domain);
I created this function which uses URL to parse. It cheats by assuming all hostnames will have either 4 or less parts.
const getDomainWithoutSubdomain = url => {
const urlParts = new URL(url).hostname.split('.')
return urlParts
.slice(0)
.slice(-(urlParts.length === 4 ? 3 : 2))
.join('.')
}
[
'https://www.google.com',
'https://www.google.co.uk',
'https://mail.google.com',
'https://www.bbc.co.uk/news',
'https://github.com',
].forEach(url => {
console.log(getDomainWithoutSubdomain(url))
})
Here is a working JSFiddle
My solution works with the assumption that the root hostname you are looking for is of the type "abc.xyz.pp".
extractDomain() returns the hostname with all the subdomains.
getRootHostName() splits the hostname by . and then based on the assumption mentioned above, it uses the shift() to remove each subdomain name.
Finally, whatever remains in parts[], it joins them by . to form the root hostname.
Javascript
var urlInput = "http://one.two.roothost.co.uk/page.html";
function extractDomain(url) {
var domain;
//find & remove protocol (http, ftp, etc.) and get domain
if (url.indexOf("://") > -1) {
domain = url.split('/')[2];
} else {
domain = url.split('/')[0];
}
//find & remove port number
domain = domain.split(':')[0];
return domain;
}
function getRootHostName(url) {
var parts = extractDomain(url).split('.');
var partsLength = parts.length - 3;
//parts.length-3 assuming root hostname is of type abc.xyz.pp
for (i = 0; i < partsLength; i++) {
parts.shift(); //remove sub-domains one by one
}
var rootDomain = parts.join('.');
return rootDomain;
}
document.getElementById("result").innerHTML = getRootHostName(urlInput);
HTML
<div id="result"></div>
EDIT 1: Updated the JSFiddle link. It was reflecting the incorrect code.
What about...
function getDomain(){
if(document.domain.length){
var parts = document.domain.replace(/^(www\.)/,"").split('.');
//is there a subdomain?
while(parts.length > 2){
//removing it from our array
var subdomain = parts.shift();
}
//getting the remaining 2 elements
var domain = parts.join('.');
return domain.replace(/(^\.*)|(\.*$)/g, "");
}
return '';
}
My solution worked for me: Get "gocustom.com" from "shop.gocustom.com"
var site_domain_name = 'shop.gocustom.com';
alert(site_domain_name);
var strsArray = site_domain_name.split('.');
var strsArrayLen = strsArray.length;
alert(strsArray[eval(strsArrayLen - 2)]+'.'+strsArray[eval(strsArrayLen - 1)])
You can try this in JavaScript:
alert(window.location.hostname);
It will return the hostname.
How to get the domain name without subdomains?
e.g. if the url is "http://one.two.roothost.co.uk/page.html" how to get "roothost.co.uk"?
Following is a solution to extract a domain name without any subdomains. This solution doesn't make any assumptions about the URL format, so it should work for any URL. Since some domain names have one suffix (.com), and some have two or more (.co.uk), to get an accurate result in all cases, we need to parse the hostname using the Public Suffix List, which contains a list of all public domain name suffixes.
Solution
First, include the public suffix list js api in a script tag in your HTML, then in JavaScript to get the hostname you can call:
var parsed = psl.parse('one.two.roothost.co.uk');
console.log(parsed.domain);
...which will return "roothost.co.uk". To get the name from the current page, you can use location.hostname instead of a static string:
var parsed = psl.parse(location.hostname);
console.log(parsed.domain);
Finally, if you need to parse a domain name directly out of a full URL string, you can use the following:
var url = "http://one.two.roothost.co.uk/page.html";
url = url.split("/")[2]; // Get the hostname
var parsed = psl.parse(url); // Parse the domain
document.getElementById("output").textContent = parsed.domain;
JSFiddle Example (it includes the entire minified library in the jsFiddle, so scroll down!): https://jsfiddle.net/6aqdbL71/2/
What about this?
function getCanonicalHost(hostname) {
const MAX_TLD_LENGTH = 3;
function isNotTLD(_) { return _.length > MAX_TLD_LENGTH; };
hostname = hostname.split('.');
hostname = hostname.slice(Math.max(0, hostname.findLastIndex(isNotTLD)));
hostname = hostname.join('.');
return hostname;
}
console.log(getCanonicalHost('mail.google.com'));
console.log(getCanonicalHost('some.google.com.ar'));
console.log(getCanonicalHost('some.another.google.com.ar'));
console.log(getCanonicalHost('foo.bar.google.com'));
console.log(getCanonicalHost('foo.bar.google.com.ar'));
console.log(getCanonicalHost('bar.google.ar'));
Its works since https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_domain_name say:
TLDs can contain special as well as latin characters. A TLD's maximum length is 63 characters, although most are around 2–3.
In https://data.iana.org/TLD/tlds-alpha-by-domain.txt are 1481 TLD, 466 of this has length around 2–3 and the most used TLD no has more than 3.
If you need a solution that works with all TLDS, here is a more complex aproach:
function getCanonicalHost(hostname) {
return getCanonicalHost.tlds.then(function(tlds) {
function isNotTLD(_) { return tlds.indexOf(_) === -1; };
hostname = hostname.toLowerCase();
hostname = hostname.split('.');
hostname = hostname.slice(Math.max(0, hostname.findLastIndex(isNotTLD)));
hostname = hostname.join('.');
return hostname;
});
}
getCanonicalHost.tlds = new Promise(function(res, rej) {
const TLD_LIST_URL= 'https://data.iana.org/TLD/tlds-alpha-by-domain.txt';
const xhr = new XMLHttpRequest();
xhr.addEventListener('error', rej);
xhr.addEventListener('load', function() {
const MAX_TLD_LENGTH = 63;
var tlds = xhr.responseText.split('\n');
tlds = tlds.map(function(_) { return _.trim().toLowerCase(); });
tlds = tlds.filter(Boolean);
tlds = tlds.filter(function(_) { return _.length < MAX_TLD_LENGTH; });
res(tlds);
});
xhr.open('GET', TLD_LIST_URL);
xhr.send();
})
getCanonicalHost('mail.google.com').then(console.log);
getCanonicalHost('some.google.com.ar').then(console.log);
getCanonicalHost('some.another.google.com.ar').then(console.log);
getCanonicalHost('foo.bar.google.com').then(console.log);
getCanonicalHost('foo.bar.google.com.ar').then(console.log);
getCanonicalHost('bar.google.ar').then(console.log);
You can use parse-domain to do the heavy lifting for you. This package considers the public suffix list and returns an easy to work with object breaking up the domain.
Here is an example from their readme:
npm install parse-domain
import { parseDomain, ParseResultType } from 'parse-domain';
const parseResult = parseDomain(
// should be a string with basic latin characters only. more details in the readme
'www.some.example.co.uk',
);
// check if the domain is listed in the public suffix list
if (parseResult.type === ParseResultType.Listed) {
const { subDomains, domain, topLevelDomains } = parseResult;
console.log(subDomains); // ["www", "some"]
console.log(domain); // "example"
console.log(topLevelDomains); // ["co", "uk"]
} else {
// more about other parseResult types in the readme
}
This works for me:
const firstTLDs = "ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|be|bf|bg|bh|bi|bj|bm|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|cl|cm|cn|co|cr|cu|cv|cw|cx|cz|de|dj|dk|dm|do|dz|ec|ee|eg|es|et|eu|fi|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jo|jp|kg|ki|km|kn|kp|kr|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|na|nc|ne|nf|ng|nl|no|nr|nu|nz|om|pa|pe|pf|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|yt".split('|');
const secondTLDs = "com|edu|gov|net|mil|org|nom|sch|caa|res|off|gob|int|tur|ip6|uri|urn|asn|act|nsw|qld|tas|vic|pro|biz|adm|adv|agr|arq|art|ato|bio|bmd|cim|cng|cnt|ecn|eco|emp|eng|esp|etc|eti|far|fnd|fot|fst|g12|ggf|imb|ind|inf|jor|jus|leg|lel|mat|med|mus|not|ntr|odo|ppg|psc|psi|qsl|rec|slg|srv|teo|tmp|trd|vet|zlg|web|ltd|sld|pol|fin|k12|lib|pri|aip|fie|eun|sci|prd|cci|pvt|mod|idv|rel|sex|gen|nic|abr|bas|cal|cam|emr|fvg|laz|lig|lom|mar|mol|pmn|pug|sar|sic|taa|tos|umb|vao|vda|ven|mie|北海道|和歌山|神奈川|鹿児島|ass|rep|tra|per|ngo|soc|grp|plc|its|air|and|bus|can|ddr|jfk|mad|nrw|nyc|ski|spy|tcm|ulm|usa|war|fhs|vgs|dep|eid|fet|fla|flå|gol|hof|hol|sel|vik|cri|iwi|ing|abo|fam|gok|gon|gop|gos|aid|atm|gsm|sos|elk|waw|est|aca|bar|cpa|jur|law|sec|plo|www|bir|cbg|jar|khv|msk|nov|nsk|ptz|rnd|spb|stv|tom|tsk|udm|vrn|cmw|kms|nkz|snz|pub|fhv|red|ens|nat|rns|rnu|bbs|tel|bel|kep|nhs|dni|fed|isa|nsn|gub|e12|tec|орг|обр|упр|alt|nis|jpn|mex|ath|iki|nid|gda|inc".split('|');
const knownSubdomains = "www|studio|mail|remote|blog|webmail|server|ns1|ns2|smtp|secure|vpn|m|shop|ftp|mail2|test|portal|ns|ww1|host|support|dev|web|bbs|ww42|squatter|mx|email|1|mail1|2|forum|owa|www2|gw|admin|store|mx1|cdn|api|exchange|app|gov|2tty|vps|govyty|hgfgdf|news|1rer|lkjkui";
function removeSubdomain(s) {
const knownSubdomainsRegExp = new RegExp(`^(${knownSubdomains})\.`, 'i');
s = s.replace(knownSubdomainsRegExp, '');
const parts = s.split('.');
while (parts.length > 3) {
parts.shift();
}
if (parts.length === 3 && ((parts[1].length > 2 && parts[2].length > 2) || (secondTLDs.indexOf(parts[1]) === -1) && firstTLDs.indexOf(parts[2]) === -1)) {
parts.shift();
}
return parts.join('.');
};
var tests = {
'www.sidanmor.com': 'sidanmor.com',
'exemple.com': 'exemple.com',
'argos.co.uk': 'argos.co.uk',
'www.civilwar.museum': 'civilwar.museum',
'www.sub.civilwar.museum': 'civilwar.museum',
'www.xxx.sub.civilwar.museum': 'civilwar.museum',
'www.exemple.com': 'exemple.com',
'main.testsite.com': 'testsite.com',
'www.ex-emple.com.ar': 'ex-emple.com.ar',
'main.test-site.co.uk': 'test-site.co.uk',
'en.tour.mysite.nl': 'tour.mysite.nl',
'www.one.lv': 'one.lv',
'www.onfdsadfsafde.lv': 'onfdsadfsafde.lv',
'aaa.onfdsadfsafde.aa': 'onfdsadfsafde.aa',
};
const firstTLDs = "ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|be|bf|bg|bh|bi|bj|bm|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|cl|cm|cn|co|cr|cu|cv|cw|cx|cz|de|dj|dk|dm|do|dz|ec|ee|eg|es|et|eu|fi|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jo|jp|kg|ki|km|kn|kp|kr|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|na|nc|ne|nf|ng|nl|no|nr|nu|nz|om|pa|pe|pf|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|yt".split('|');
const secondTLDs = "com|edu|gov|net|mil|org|nom|sch|caa|res|off|gob|int|tur|ip6|uri|urn|asn|act|nsw|qld|tas|vic|pro|biz|adm|adv|agr|arq|art|ato|bio|bmd|cim|cng|cnt|ecn|eco|emp|eng|esp|etc|eti|far|fnd|fot|fst|g12|ggf|imb|ind|inf|jor|jus|leg|lel|mat|med|mus|not|ntr|odo|ppg|psc|psi|qsl|rec|slg|srv|teo|tmp|trd|vet|zlg|web|ltd|sld|pol|fin|k12|lib|pri|aip|fie|eun|sci|prd|cci|pvt|mod|idv|rel|sex|gen|nic|abr|bas|cal|cam|emr|fvg|laz|lig|lom|mar|mol|pmn|pug|sar|sic|taa|tos|umb|vao|vda|ven|mie|北海道|和歌山|神奈川|鹿児島|ass|rep|tra|per|ngo|soc|grp|plc|its|air|and|bus|can|ddr|jfk|mad|nrw|nyc|ski|spy|tcm|ulm|usa|war|fhs|vgs|dep|eid|fet|fla|flå|gol|hof|hol|sel|vik|cri|iwi|ing|abo|fam|gok|gon|gop|gos|aid|atm|gsm|sos|elk|waw|est|aca|bar|cpa|jur|law|sec|plo|www|bir|cbg|jar|khv|msk|nov|nsk|ptz|rnd|spb|stv|tom|tsk|udm|vrn|cmw|kms|nkz|snz|pub|fhv|red|ens|nat|rns|rnu|bbs|tel|bel|kep|nhs|dni|fed|isa|nsn|gub|e12|tec|орг|обр|упр|alt|nis|jpn|mex|ath|iki|nid|gda|inc".split('|');
const knownSubdomains = "www|studio|mail|remote|blog|webmail|server|ns1|ns2|smtp|secure|vpn|m|shop|ftp|mail2|test|portal|ns|ww1|host|support|dev|web|bbs|ww42|squatter|mx|email|1|mail1|2|forum|owa|www2|gw|admin|store|mx1|cdn|api|exchange|app|gov|2tty|vps|govyty|hgfgdf|news|1rer|lkjkui";
function removeSubdomain(s) {
const knownSubdomainsRegExp = new RegExp(`^(${knownSubdomains})\.`, 'i');
s = s.replace(knownSubdomainsRegExp, '');
const parts = s.split('.');
while (parts.length > 3) {
parts.shift();
}
if (parts.length === 3 && ((parts[1].length > 2 && parts[2].length > 2) || (secondTLDs.indexOf(parts[1]) === -1) && firstTLDs.indexOf(parts[2]) === -1)) {
parts.shift();
}
return parts.join('.');
};
for (var test in tests) {
if (tests.hasOwnProperty(test)) {
var t = test;
var e = tests[test];
var r = removeSubdomain(test);
var s = e === r;
if (s) {
console.log('OK: "' + t + '" should be "' + e + '" and it is really "' + r + '"');
} else {
console.log('Fail: "' + t + '" should be "' + e + '" but it is NOT "' + r + '"');
}
}
}
Referance:
psl.min.js file
Maximillian Laumeister Answer to this question
The most popular subdomains on the internet
Simplest solution:
var domain='https://'+window.location.hostname.split('.')[window.location.hostname.split('.').length-2]+'.'+window.location.hostname.split('.')[window.location.hostname.split('.').length-1];
alert(domain);
I created this function which uses URL to parse. It cheats by assuming all hostnames will have either 4 or less parts.
const getDomainWithoutSubdomain = url => {
const urlParts = new URL(url).hostname.split('.')
return urlParts
.slice(0)
.slice(-(urlParts.length === 4 ? 3 : 2))
.join('.')
}
[
'https://www.google.com',
'https://www.google.co.uk',
'https://mail.google.com',
'https://www.bbc.co.uk/news',
'https://github.com',
].forEach(url => {
console.log(getDomainWithoutSubdomain(url))
})
Here is a working JSFiddle
My solution works with the assumption that the root hostname you are looking for is of the type "abc.xyz.pp".
extractDomain() returns the hostname with all the subdomains.
getRootHostName() splits the hostname by . and then based on the assumption mentioned above, it uses the shift() to remove each subdomain name.
Finally, whatever remains in parts[], it joins them by . to form the root hostname.
Javascript
var urlInput = "http://one.two.roothost.co.uk/page.html";
function extractDomain(url) {
var domain;
//find & remove protocol (http, ftp, etc.) and get domain
if (url.indexOf("://") > -1) {
domain = url.split('/')[2];
} else {
domain = url.split('/')[0];
}
//find & remove port number
domain = domain.split(':')[0];
return domain;
}
function getRootHostName(url) {
var parts = extractDomain(url).split('.');
var partsLength = parts.length - 3;
//parts.length-3 assuming root hostname is of type abc.xyz.pp
for (i = 0; i < partsLength; i++) {
parts.shift(); //remove sub-domains one by one
}
var rootDomain = parts.join('.');
return rootDomain;
}
document.getElementById("result").innerHTML = getRootHostName(urlInput);
HTML
<div id="result"></div>
EDIT 1: Updated the JSFiddle link. It was reflecting the incorrect code.
What about...
function getDomain(){
if(document.domain.length){
var parts = document.domain.replace(/^(www\.)/,"").split('.');
//is there a subdomain?
while(parts.length > 2){
//removing it from our array
var subdomain = parts.shift();
}
//getting the remaining 2 elements
var domain = parts.join('.');
return domain.replace(/(^\.*)|(\.*$)/g, "");
}
return '';
}
My solution worked for me: Get "gocustom.com" from "shop.gocustom.com"
var site_domain_name = 'shop.gocustom.com';
alert(site_domain_name);
var strsArray = site_domain_name.split('.');
var strsArrayLen = strsArray.length;
alert(strsArray[eval(strsArrayLen - 2)]+'.'+strsArray[eval(strsArrayLen - 1)])
You can try this in JavaScript:
alert(window.location.hostname);
It will return the hostname.
With javascript how can I add a query string parameter to the url if not present or if it present, update the current value? I am using jquery for my client side development.
I wrote the following function which accomplishes what I want to achieve:
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
return uri + separator + key + "=" + value;
}
}
Update (2020): URLSearchParams is now supported by all modern browsers.
The URLSearchParams utility can be useful for this in combination with window.location.search. For example:
if ('URLSearchParams' in window) {
var searchParams = new URLSearchParams(window.location.search);
searchParams.set("foo", "bar");
window.location.search = searchParams.toString();
}
Now foo has been set to bar regardless of whether or not it already existed.
However, the above assignment to window.location.search will cause a page load, so if that's not desirable use the History API as follows:
if ('URLSearchParams' in window) {
var searchParams = new URLSearchParams(window.location.search)
searchParams.set("foo", "bar");
var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
history.pushState(null, '', newRelativePathQuery);
}
Now you don't need to write your own regex or logic to handle the possible existence of query strings.
However, browser support is poor as it's currently experimental and only in use in recent versions of Chrome, Firefox, Safari, iOS Safari, Android Browser, Android Chrome and Opera. Use with a polyfill if you do decide to use it.
I have expanded the solution and combined it with another that I found to replace/update/remove the querystring parameters based on the users input and taking the urls anchor into consideration.
Not supplying a value will remove the parameter, supplying one will add/update the parameter. If no URL is supplied, it will be grabbed from window.location
function UpdateQueryString(key, value, url) {
if (!url) url = window.location.href;
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
hash;
if (re.test(url)) {
if (typeof value !== 'undefined' && value !== null) {
return url.replace(re, '$1' + key + "=" + value + '$2$3');
}
else {
hash = url.split('#');
url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
url += '#' + hash[1];
}
return url;
}
}
else {
if (typeof value !== 'undefined' && value !== null) {
var separator = url.indexOf('?') !== -1 ? '&' : '?';
hash = url.split('#');
url = hash[0] + separator + key + '=' + value;
if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
url += '#' + hash[1];
}
return url;
}
else {
return url;
}
}
}
Update
There was a bug when removing the first parameter in the querystring, I have reworked the regex and test to include a fix.
Second Update
As suggested by #JarónBarends - Tweak value check to check against undefined and null to allow setting 0 values
Third Update
There was a bug where removing a querystring variable directly before a hashtag would lose the hashtag symbol which has been fixed
Fourth Update
Thanks #rooby for pointing out a regex optimization in the first RegExp object.
Set initial regex to ([?&]) due to issue with using (\?|&) found by #YonatanKarni
Fifth Update
Removing declaring hash var in if/else statement
Based on #amateur's answer (and now incorporating the fix from #j_walker_dev comment), but taking into account the comment about hash tags in the url I use the following:
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
} else {
var hash = '';
if( uri.indexOf('#') !== -1 ){
hash = uri.replace(/.*#/, '#');
uri = uri.replace(/#.*/, '');
}
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
return uri + separator + key + "=" + value + hash;
}
}
Edited to fix [?|&] in regex which should of course be [?&] as pointed out in the comments
Edit: Alternative version to support removing URL params as well. I have used value === undefined as the way to indicate removal. Could use value === false or even a separate input param as wanted.
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");
if( value === undefined ) {
if (uri.match(re)) {
return uri.replace(re, '$1$2').replace(/[?&]$/, '').replaceAll(/([?&])&+/g, '$1').replace(/[?&]#/, '#');
} else {
return uri;
}
} else {
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
} else {
var hash = '';
if( uri.indexOf('#') !== -1 ){
hash = uri.replace(/.*#/, '#');
uri = uri.replace(/#.*/, '');
}
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
return uri + separator + key + "=" + value + hash;
}
}
}
See it in action at https://jsfiddle.net/cdt16wex/
You can use the browser's native URL API to do this in a fairly simple way, where key and value are your parameter name and parameter value respectively.
const url = new URL(location.href);
url.searchParams.set(key, value);
history.pushState(null, '', url);
This will preserve everything about the URL and only change or add the one query param. You can also use replaceState instead of pushState if you don't want it to create a new browser history entry.
Thanks to modern javascript, node.js and browsers support, we can get out of 3rd-party library whirlpool (jquery, query-string etc.) and DRY ourselves.
Here are javascript(node.js) and typescript version for a function that adds or updates query params of given url:
Javascript
const getUriWithParam = (baseUrl, params) => {
const Url = new URL(baseUrl);
const urlParams = new URLSearchParams(Url.search);
for (const key in params) {
if (params[key] !== undefined) {
urlParams.set(key, params[key]);
}
}
Url.search = urlParams.toString();
return Url.toString();
};
console.info('expected: https://example.com/?foo=bar');
console.log(getUriWithParam("https://example.com", {foo: "bar"}));
console.info('expected: https://example.com/slug?foo=bar#hash');
console.log(getUriWithParam("https://example.com/slug#hash", {foo: "bar"}));
console.info('expected: https://example.com/?bar=baz&foo=bar');
console.log(getUriWithParam("https://example.com?bar=baz", {foo: "bar"}));
console.info('expected: https://example.com/?foo=baz&bar=baz');
console.log(getUriWithParam("https://example.com?foo=bar&bar=baz", {foo: "baz"}));
Typescript
const getUriWithParam = (
baseUrl: string,
params: Record<string, any>
): string => {
const Url = new URL(baseUrl);
const urlParams: URLSearchParams = new URLSearchParams(Url.search);
for (const key in params) {
if (params[key] !== undefined) {
urlParams.set(key, params[key]);
}
}
Url.search = urlParams.toString();
return Url.toString();
};
For React Native
URL is not implemented in React Native. So you have to install react-native-url-polyfill beforehand.
For object params
See the second solution in this answer
Here is my library to do that: https://github.com/Mikhus/jsurl
var u = new Url;
u.query.param='value'; // adds or replaces the param
alert(u)
If it's not set or want to update with a new value you can use:
window.location.search = 'param=value'; // or param=new_value
This is in simple Javascript, by the way.
EDIT
You may want to try using the jquery query-object plugin
window.location.search =
jQuery.query.set("param", 5);
I realize this question is old and has been answered to death, but here's my stab at it. I'm trying to reinvent the wheel here because I was using the currently accepted answer and the mishandling of URL fragments recently bit me in a project.
The function is below. It's quite long, but it was made to be as resilient as possible. I would love suggestions for shortening/improving it. I put together a small jsFiddle test suite for it (or other similar functions). If a function can pass every one of the tests there, I say it's probably good to go.
Update: I came across a cool function for using the DOM to parse URLs, so I incorporated that technique here. It makes the function shorter and more reliable. Props to the author of that function.
/**
* Add or update a query string parameter. If no URI is given, we use the current
* window.location.href value for the URI.
*
* Based on the DOM URL parser described here:
* http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
*
* #param (string) uri Optional: The URI to add or update a parameter in
* #param (string) key The key to add or update
* #param (string) value The new value to set for key
*
* Tested on Chrome 34, Firefox 29, IE 7 and 11
*/
function update_query_string( uri, key, value ) {
// Use window URL if no query string is provided
if ( ! uri ) { uri = window.location.href; }
// Create a dummy element to parse the URI with
var a = document.createElement( 'a' ),
// match the key, optional square brackets, an equals sign or end of string, the optional value
reg_ex = new RegExp( key + '((?:\\[[^\\]]*\\])?)(=|$)(.*)' ),
// Setup some additional variables
qs,
qs_len,
key_found = false;
// Use the JS API to parse the URI
a.href = uri;
// If the URI doesn't have a query string, add it and return
if ( ! a.search ) {
a.search = '?' + key + '=' + value;
return a.href;
}
// Split the query string by ampersands
qs = a.search.replace( /^\?/, '' ).split( /&(?:amp;)?/ );
qs_len = qs.length;
// Loop through each query string part
while ( qs_len > 0 ) {
qs_len--;
// Remove empty elements to prevent double ampersands
if ( ! qs[qs_len] ) { qs.splice(qs_len, 1); continue; }
// Check if the current part matches our key
if ( reg_ex.test( qs[qs_len] ) ) {
// Replace the current value
qs[qs_len] = qs[qs_len].replace( reg_ex, key + '$1' ) + '=' + value;
key_found = true;
}
}
// If we haven't replaced any occurrences above, add the new parameter and value
if ( ! key_found ) { qs.push( key + '=' + value ); }
// Set the new query string
a.search = '?' + qs.join( '&' );
return a.href;
}
window.location.search is read/write.
However - modifying the query string will redirect the page you're on and cause a refresh from the server.
If what you're attempting to do is maintain client side state (and potentially make it bookmark-able), you'll want to modify the URL hash instead of the query string, which keeps you on the same page (window.location.hash is read/write). This is how web sites like twitter.com do this.
You'll also want the back button to work, you'll have to bind javascript events to the hash change event, a good plugin for that is http://benalman.com/projects/jquery-hashchange-plugin/
Here's my approach: The location.params() function (shown below) can be used as a getter or setter. Examples:
Given the URL is http://example.com/?foo=bar&baz#some-hash,
location.params() will return an object with all the query parameters: {foo: 'bar', baz: true}.
location.params('foo') will return 'bar'.
location.params({foo: undefined, hello: 'world', test: true}) will change the URL to http://example.com/?baz&hello=world&test#some-hash.
Here is the params() function, which can optionally be assigned to the window.location object.
location.params = function(params) {
var obj = {}, i, parts, len, key, value;
if (typeof params === 'string') {
value = location.search.match(new RegExp('[?&]' + params + '=?([^&]*)[&#$]?'));
return value ? value[1] : undefined;
}
var _params = location.search.substr(1).split('&');
for (i = 0, len = _params.length; i < len; i++) {
parts = _params[i].split('=');
if (! parts[0]) {continue;}
obj[parts[0]] = parts[1] || true;
}
if (typeof params !== 'object') {return obj;}
for (key in params) {
value = params[key];
if (typeof value === 'undefined') {
delete obj[key];
} else {
obj[key] = value;
}
}
parts = [];
for (key in obj) {
parts.push(key + (obj[key] === true ? '' : '=' + obj[key]));
}
location.search = parts.join('&');
};
I know this is quite old but i want to fires my working version in here.
function addOrUpdateUrlParam(uri, paramKey, paramVal) {
var re = new RegExp("([?&])" + paramKey + "=[^&#]*", "i");
if (re.test(uri)) {
uri = uri.replace(re, '$1' + paramKey + "=" + paramVal);
} else {
var separator = /\?/.test(uri) ? "&" : "?";
uri = uri + separator + paramKey + "=" + paramVal;
}
return uri;
}
jQuery(document).ready(function($) {
$('#paramKey,#paramValue').on('change', function() {
if ($('#paramKey').val() != "" && $('#paramValue').val() != "") {
$('#uri').val(addOrUpdateUrlParam($('#uri').val(), $('#paramKey').val(), $('#paramValue').val()));
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input style="width:100%" type="text" id="uri" value="http://www.example.com/text.php">
<label style="display:block;">paramKey
<input type="text" id="paramKey">
</label>
<label style="display:block;">paramValue
<input type="text" id="paramValue">
</label>
NOTE This is a modified version of #elreimundo
It's so simple with URLSearchParams, supported in all modern browsers (caniuse).
let p = new URLSearchParams();
p.set("foo", "bar");
p.set("name", "Jack & Jill?");
console.log("http://example.com/?" + p.toString());
If you want to modify the existing URL, construct the object like this: new URLSearchParams(window.location.search) and assign the string to window.location.search.
My take from here (compatible with "use strict"; does not really use jQuery):
function decodeURIParams(query) {
if (query == null)
query = window.location.search;
if (query[0] == '?')
query = query.substring(1);
var params = query.split('&');
var result = {};
for (var i = 0; i < params.length; i++) {
var param = params[i];
var pos = param.indexOf('=');
if (pos >= 0) {
var key = decodeURIComponent(param.substring(0, pos));
var val = decodeURIComponent(param.substring(pos + 1));
result[key] = val;
} else {
var key = decodeURIComponent(param);
result[key] = true;
}
}
return result;
}
function encodeURIParams(params, addQuestionMark) {
var pairs = [];
for (var key in params) if (params.hasOwnProperty(key)) {
var value = params[key];
if (value != null) /* matches null and undefined */ {
pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value))
}
}
if (pairs.length == 0)
return '';
return (addQuestionMark ? '?' : '') + pairs.join('&');
}
//// alternative to $.extend if not using jQuery:
// function mergeObjects(destination, source) {
// for (var key in source) if (source.hasOwnProperty(key)) {
// destination[key] = source[key];
// }
// return destination;
// }
function navigateWithURIParams(newParams) {
window.location.search = encodeURIParams($.extend(decodeURIParams(), newParams), true);
}
Example usage:
// add/update parameters
navigateWithURIParams({ foo: 'bar', boz: 42 });
// remove parameter
navigateWithURIParams({ foo: null });
// submit the given form by adding/replacing URI parameters (with jQuery)
$('.filter-form').submit(function(e) {
e.preventDefault();
navigateWithURIParams(decodeURIParams($(this).serialize()));
});
Based on the answer #ellemayo gave, I came up with the following solution that allows for disabling of the hash tag if desired:
function updateQueryString(key, value, options) {
if (!options) options = {};
var url = options.url || location.href;
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"), hash;
hash = url.split('#');
url = hash[0];
if (re.test(url)) {
if (typeof value !== 'undefined' && value !== null) {
url = url.replace(re, '$1' + key + "=" + value + '$2$3');
} else {
url = url.replace(re, '$1$3').replace(/(&|\?)$/, '');
}
} else if (typeof value !== 'undefined' && value !== null) {
var separator = url.indexOf('?') !== -1 ? '&' : '?';
url = url + separator + key + '=' + value;
}
if ((typeof options.hash === 'undefined' || options.hash) &&
typeof hash[1] !== 'undefined' && hash[1] !== null)
url += '#' + hash[1];
return url;
}
Call it like this:
updateQueryString('foo', 'bar', {
url: 'http://my.example.com#hash',
hash: false
});
Results in:
http://my.example.com?foo=bar
Here is a shorter version that takes care of
query with or without a given parameter
query with multiple parameter values
query containing hash
Code:
var setQueryParameter = function(uri, key, value) {
var re = new RegExp("([?&])("+ key + "=)[^&#]*", "g");
if (uri.match(re))
return uri.replace(re, '$1$2' + value);
// need to add parameter to URI
var paramString = (uri.indexOf('?') < 0 ? "?" : "&") + key + "=" + value;
var hashIndex = uri.indexOf('#');
if (hashIndex < 0)
return uri + paramString;
else
return uri.substring(0, hashIndex) + paramString + uri.substring(hashIndex);
}
The regex description can be found here.
NOTE: This solution is based on #amateur answer, but with many improvements.
Code that appends a list of parameters to an existing url using ES6 and jQuery:
class UrlBuilder {
static appendParametersToUrl(baseUrl, listOfParams) {
if (jQuery.isEmptyObject(listOfParams)) {
return baseUrl;
}
const newParams = jQuery.param(listOfParams);
let partsWithHash = baseUrl.split('#');
let partsWithParams = partsWithHash[0].split('?');
let previousParams = '?' + ((partsWithParams.length === 2) ? partsWithParams[1] + '&' : '');
let previousHash = (partsWithHash.length === 2) ? '#' + partsWithHash[1] : '';
return partsWithParams[0] + previousParams + newParams + previousHash;
}
}
Where listOfParams is like
const listOfParams = {
'name_1': 'value_1',
'name_2': 'value_2',
'name_N': 'value_N',
};
Example of Usage:
UrlBuilder.appendParametersToUrl(urlBase, listOfParams);
Fast tests:
url = 'http://hello.world';
console.log('=> ', UrlParameters.appendParametersToUrl(url, null));
// Output: http://hello.world
url = 'http://hello.world#h1';
console.log('=> ', UrlParameters.appendParametersToUrl(url, null));
// Output: http://hello.world#h1
url = 'http://hello.world';
params = {'p1': 'v1', 'p2': 'v2'};
console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
// Output: http://hello.world?p1=v1&p2=v2
url = 'http://hello.world?p0=v0';
params = {'p1': 'v1', 'p2': 'v2'};
console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
// Output: http://hello.world?p0=v0&p1=v1&p2=v2
url = 'http://hello.world#h1';
params = {'p1': 'v1', 'p2': 'v2'};
console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
// Output: http://hello.world?p1=v1&p2=v2#h1
url = 'http://hello.world?p0=v0#h1';
params = {'p1': 'v1', 'p2': 'v2'};
console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
// Output: http://hello.world?p0=v0&p1=v1&p2=v2#h1
To give an code example for modifying window.location.search as suggested by Gal and tradyblix:
var qs = window.location.search || "?";
var param = key + "=" + value; // remember to URI encode your parameters
if (qs.length > 1) {
// more than just the question mark, so append with ampersand
qs = qs + "&";
}
qs = qs + param;
window.location.search = qs;
A different approach without using regular expressions. Supports 'hash' anchors at the end of the url as well as multiple question mark charcters (?). Should be slightly faster than the regular expression approach.
function setUrlParameter(url, key, value) {
var parts = url.split("#", 2), anchor = parts.length > 1 ? "#" + parts[1] : '';
var query = (url = parts[0]).split("?", 2);
if (query.length === 1)
return url + "?" + key + "=" + value + anchor;
for (var params = query[query.length - 1].split("&"), i = 0; i < params.length; i++)
if (params[i].toLowerCase().startsWith(key.toLowerCase() + "="))
return params[i] = key + "=" + value, query[query.length - 1] = params.join("&"), query.join("?") + anchor;
return url + "&" + key + "=" + value + anchor
}
Use this function to add, remove and modify query string parameter from URL based on jquery
/**
#param String url
#param object param {key: value} query parameter
*/
function modifyURLQuery(url, param){
var value = {};
var query = String(url).split('?');
if (query[1]) {
var part = query[1].split('&');
for (i = 0; i < part.length; i++) {
var data = part[i].split('=');
if (data[0] && data[1]) {
value[data[0]] = data[1];
}
}
}
value = $.extend(value, param);
// Remove empty value
for (i in value){
if(!value[i]){
delete value[i];
}
}
// Return url with modified parameter
if(value){
return query[0] + '?' + $.param(value);
} else {
return query[0];
}
}
Add new and modify existing parameter to url
var new_url = modifyURLQuery("http://google.com?foo=34", {foo: 50, bar: 45});
// Result: http://google.com?foo=50&bar=45
Remove existing
var new_url = modifyURLQuery("http://google.com?foo=50&bar=45", {bar: null});
// Result: http://google.com?foo=50
Here's my slightly different approach to this, written as an excercise
function addOrChangeParameters( url, params )
{
let splitParams = {};
let splitPath = (/(.*)[?](.*)/).exec(url);
if ( splitPath && splitPath[2] )
splitPath[2].split("&").forEach( k => { let d = k.split("="); splitParams[d[0]] = d[1]; } );
let newParams = Object.assign( splitParams, params );
let finalParams = Object.keys(newParams).map( (a) => a+"="+newParams[a] ).join("&");
return splitPath ? (splitPath[1] + "?" + finalParams) : (url + "?" + finalParams);
}
usage:
const url = "http://testing.com/path?empty&value1=test&id=3";
addOrChangeParameters( url, {value1:1, empty:"empty", new:0} )
"http://testing.com/path?empty=empty&value1=1&id=3&new=0"
This answer is just a small tweak of ellemayo's answer. It will automatically update the URL instead of just returning the updated string.
function _updateQueryString(key, value, url) {
if (!url) url = window.location.href;
let updated = ''
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
hash;
if (re.test(url)) {
if (typeof value !== 'undefined' && value !== null) {
updated = url.replace(re, '$1' + key + "=" + value + '$2$3');
}
else {
hash = url.split('#');
url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
url += '#' + hash[1];
}
updated = url;
}
}
else {
if (typeof value !== 'undefined' && value !== null) {
var separator = url.indexOf('?') !== -1 ? '&' : '?';
hash = url.split('#');
url = hash[0] + separator + key + '=' + value;
if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
url += '#' + hash[1];
}
updated = url;
}
else {
updated = url;
}
}
window.history.replaceState({ path: updated }, '', updated);
}
Java script code to find a specific query string and replace its value *
('input.letter').click(function () {
//0- prepare values
var qsTargeted = 'letter=' + this.value; //"letter=A";
var windowUrl = '';
var qskey = qsTargeted.split('=')[0];
var qsvalue = qsTargeted.split('=')[1];
//1- get row url
var originalURL = window.location.href;
//2- get query string part, and url
if (originalURL.split('?').length > 1) //qs is exists
{
windowUrl = originalURL.split('?')[0];
var qs = originalURL.split('?')[1];
//3- get list of query strings
var qsArray = qs.split('&');
var flag = false;
//4- try to find query string key
for (var i = 0; i < qsArray.length; i++) {
if (qsArray[i].split('=').length > 0) {
if (qskey == qsArray[i].split('=')[0]) {
//exists key
qsArray[i] = qskey + '=' + qsvalue;
flag = true;
break;
}
}
}
if (!flag)// //5- if exists modify,else add
{
qsArray.push(qsTargeted);
}
var finalQs = qsArray.join('&');
//6- prepare final url
window.location = windowUrl + '?' + finalQs;
}
else {
//6- prepare final url
//add query string
window.location = originalURL + '?' + qsTargeted;
}
})
});
Here's an alternative method using the inbuilt properties of the anchor HTML element:
Handles multi-valued parameters.
No risk of modifying the # fragment, or anything other than the query string itself.
May be a little easier to read? But it is longer.
var a = document.createElement('a'),
getHrefWithUpdatedQueryString = function(param, value) {
return updatedQueryString(window.location.href, param, value);
},
updatedQueryString = function(url, param, value) {
/*
A function which modifies the query string
by setting one parameter to a single value.
Any other instances of parameter will be removed/replaced.
*/
var fragment = encodeURIComponent(param) +
'=' + encodeURIComponent(value);
a.href = url;
if (a.search.length === 0) {
a.search = '?' + fragment;
} else {
var didReplace = false,
// Remove leading '?'
parts = a.search.substring(1)
// Break into pieces
.split('&'),
reassemble = [],
len = parts.length;
for (var i = 0; i < len; i++) {
var pieces = parts[i].split('=');
if (pieces[0] === param) {
if (!didReplace) {
reassemble.push('&' + fragment);
didReplace = true;
}
} else {
reassemble.push(parts[i]);
}
}
if (!didReplace) {
reassemble.push('&' + fragment);
}
a.search = reassemble.join('&');
}
return a.href;
};
if you want to set multiple parameters at once:
function updateQueryStringParameters(uri, params) {
for(key in params){
var value = params[key],
re = new RegExp("([?&])" + key + "=.*?(&|$)", "i"),
separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
uri = uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
uri = uri + separator + key + "=" + value;
}
}
return uri;
}
same function as #amateur's
if jslint gives you an error add this after the for loop
if(params.hasOwnProperty(key))
There are a lot of awkward and unnecessarily complicated answers on this page. The highest rated one, #amateur's, is quite good, although it has a bit of unnecessary fluff in the RegExp. Here is a slightly more optimal solution with cleaner RegExp and a cleaner replace call:
function updateQueryStringParamsNoHash(uri, key, value) {
var re = new RegExp("([?&])" + key + "=[^&]*", "i");
return re.test(uri)
? uri.replace(re, '$1' + key + "=" + value)
: uri + separator + key + "=" + value
;
}
As an added bonus, if uri is not a string, you won't get errors for trying to call match or replace on something that may not implement those methods.
And if you want to handle the case of a hash (and you've already done a check for properly formatted HTML), you can leverage the existing function instead of writing a new function containing the same logic:
function updateQueryStringParams(url, key, value) {
var splitURL = url.split('#');
var hash = splitURL[1];
var uri = updateQueryStringParamsNoHash(splitURL[0]);
return hash == null ? uri : uri + '#' + hash;
}
Or you can make some slight changes to #Adam's otherwise excellent answer:
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=[^&#]*", "i");
if (re.test(uri)) {
return uri.replace(re, '$1' + key + "=" + value);
} else {
var matchData = uri.match(/^([^#]*)(#.*)?$/);
var separator = /\?/.test(uri) ? "&" : "?";
return matchData[0] + separator + key + "=" + value + (matchData[1] || '');
}
}
This should serve the purpose:
function updateQueryString(url, key, value) {
var arr = url.split("#");
var url = arr[0];
var fragmentId = arr[1];
var updatedQS = "";
if (url.indexOf("?") == -1) {
updatedQS = encodeURIComponent(key) + "=" + encodeURIComponent(value);
}
else {
updatedQS = addOrModifyQS(url.substring(url.indexOf("?") + 1), key, value);
}
url = url.substring(0, url.indexOf("?")) + "?" + updatedQS;
if (typeof fragmentId !== 'undefined') {
url = url + "#" + fragmentId;
}
return url;
}
function addOrModifyQS(queryStrings, key, value) {
var oldQueryStrings = queryStrings.split("&");
var newQueryStrings = new Array();
var isNewKey = true;
for (var i in oldQueryStrings) {
var currItem = oldQueryStrings[i];
var searchKey = key + "=";
if (currItem.indexOf(searchKey) != -1) {
currItem = encodeURIComponent(key) + "=" + encodeURIComponent(value);
isNewKey = false;
}
newQueryStrings.push(currItem);
}
if (isNewKey) {
newQueryStrings.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
}
return newQueryStrings.join("&");
}
By using jQuery we can do like below
var query_object = $.query_string;
query_object["KEY"] = "VALUE";
var new_url = window.location.pathname + '?'+$.param(query_object)
In variable new_url we will have new query parameters.
Reference: http://api.jquery.com/jquery.param/
I wanted something that:
Uses the browser's native URL API
Can add, update, get, or delete
Expects the query string after the hash e.g. for single page applications
function queryParam(options = {}) {
var defaults = {
method: 'set',
url: window.location.href,
key: undefined,
value: undefined,
}
for (var prop in defaults) {
options[prop] = typeof options[prop] !== 'undefined' ? options[prop] : defaults[prop]
}
const existing = (options.url.lastIndexOf('?') > options.url.lastIndexOf('#')) ? options.url.substr(options.url.lastIndexOf('?') + 1) : ''
const query = new URLSearchParams(existing)
if (options.method === 'set') {
query.set(options.key, options.value)
return `${options.url.replace(`?${existing}`, '')}?${query.toString()}`
} else if (options.method === 'get') {
const val = query.get(options.key)
let result = val === null ? val : val.toString()
return result
} else if (options.method === 'delete') {
query.delete(options.key)
let result = `${options.url.replace(`?${existing}`, '')}?${query.toString()}`
const lastChar = result.charAt(result.length - 1)
if (lastChar === '?') {
result = `${options.url.replace(`?${existing}`, '')}`
}
return result
}
}
// Usage:
let url = 'https://example.com/sandbox/#page/'
url = queryParam({
url,
method: 'set',
key: 'my-first-param',
value: 'me'
})
console.log(url)
url = queryParam({
url,
method: 'set',
key: 'my-second-param',
value: 'you'
})
console.log(url)
url = queryParam({
url,
method: 'set',
key: 'my-second-param',
value: 'whomever'
})
console.log(url)
url = queryParam({
url,
method: 'delete',
key: 'my-first-param'
})
console.log(url)
const mySecondParam = queryParam({
url,
method: 'get',
key: 'my-second-param',
})
console.log(mySecondParam)
url = queryParam({
url,
method: 'delete',
key: 'my-second-param'
})
console.log(url)
Yeah I had an issue where my querystring would overflow and duplicate, but this was due to my own sluggishness. so I played a bit and worked up some js jquery(actualy sizzle) and C# magick.
So i just realized that after the server has done with the passed values, the values doesn't matter anymore, there is no reuse, if the client wanted to do the same thing evidently it will always be a new request, even if its the same parameters being passed. And thats all clientside, so some caching/cookies etc could be cool in that regards.
JS:
$(document).ready(function () {
$('#ser').click(function () {
SerializeIT();
});
function SerializeIT() {
var baseUrl = "";
baseUrl = getBaseUrlFromBrowserUrl(window.location.toString());
var myQueryString = "";
funkyMethodChangingStuff(); //whatever else before serializing and creating the querystring
myQueryString = $('#fr2').serialize();
window.location.replace(baseUrl + "?" + myQueryString);
}
function getBaseUrlFromBrowserUrl(szurl) {
return szurl.split("?")[0];
}
function funkyMethodChangingStuff(){
//do stuff to whatever is in fr2
}
});
HTML:
<div id="fr2">
<input type="text" name="qURL" value="http://somewhere.com" />
<input type="text" name="qSPart" value="someSearchPattern" />
</div>
<button id="ser">Serialize! and go play with the server.</button>
C#:
using System.Web;
using System.Text;
using System.Collections.Specialized;
public partial class SomeCoolWebApp : System.Web.UI.Page
{
string weburl = string.Empty;
string partName = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
string loadurl = HttpContext.Current.Request.RawUrl;
string querySZ = null;
int isQuery = loadurl.IndexOf('?');
if (isQuery == -1) {
//If There Was no Query
}
else if (isQuery >= 1) {
querySZ = (isQuery < loadurl.Length - 1) ? loadurl.Substring(isQuery + 1) : string.Empty;
string[] getSingleQuery = querySZ.Split('?');
querySZ = getSingleQuery[0];
NameValueCollection qs = null;
qs = HttpUtility.ParseQueryString(querySZ);
weburl = qs["qURL"];
partName = qs["qSPart"];
//call some great method thisPageRocks(weburl,partName); or whatever.
}
}
}
Okay criticism is welcome (this was a nightly concoction so feel free to note adjustments). If this helped at all, thumb it up, Happy Coding.
No duplicates, each request as unique as you modified it, and due to how this is structured,easy to add more queries dynamicaly from wthin the dom.