Existe-t-il un meilleur moyen de supprimer un paramètre d'une chaîne de requête dans une chaîne d'URL en JavaScript standard autrement qu'en utilisant une expression régulière?
Voici ce que j'ai trouvé jusqu'ici qui semble fonctionner dans mes tests, mais je n'aime pas réinventer l'analyse de chaîne de requête!
function RemoveParameterFromUrl( url, parameter ) {
if( typeof parameter == "undefined" || parameter == null || parameter == "" ) throw new Error( "parameter is required" );
url = url.replace( new RegExp( "\\b" + parameter + "=[^&;]+[&;]?", "gi" ), "" ); "$1" );
// remove any leftover crud
url = url.replace( /[&;]$/, "" );
return url;
}
"[&;]?" + parameter + "=[^&;]+"
Semble dangereux car le paramètre «bar» correspond à:
?a=b&foobar=c
De plus, cela échouera si parameter
contient des caractères spéciaux dans RegExp, tels que ‘.’. Et comme ce n'est pas une expression rationnelle globale, cela ne supprimerait qu'une instance du paramètre.
Je ne voudrais pas utiliser un simple RegExp pour cela, je voudrais analyser les paramètres et perdre ceux que vous ne voulez pas.
function removeURLParameter(url, parameter) {
//prefer to use l.search if you have a location/link object
var urlparts = url.split('?');
if (urlparts.length >= 2) {
var prefix = encodeURIComponent(parameter) + '=';
var pars = urlparts[1].split(/[&;]/g);
//reverse iteration as may be destructive
for (var i = pars.length; i-- > 0;) {
//idiom for string.startsWith
if (pars[i].lastIndexOf(prefix, 0) !== -1) {
pars.splice(i, 1);
}
}
return urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : '');
}
return url;
}
Copié à partir de la réponse bobince, mais le faisant supporter les points d'interrogation dans la chaîne de requête, par exemple
http://www.google.com/search?q=test????+something&aq=f
Est-il valide d'avoir plus d'un point d'interrogation dans une URL?
function removeUrlParameter(url, parameter) {
var urlParts = url.split('?');
if (urlParts.length >= 2) {
// Get first part, and remove from array
var urlBase = urlParts.shift();
// Join it back up
var queryString = urlParts.join('?');
var prefix = encodeURIComponent(parameter) + '=';
var parts = queryString.split(/[&;]/g);
// Reverse iteration as may be destructive
for (var i = parts.length; i-- > 0; ) {
// Idiom for string.startsWith
if (parts[i].lastIndexOf(prefix, 0) !== -1) {
parts.splice(i, 1);
}
}
url = urlBase + '?' + parts.join('&');
}
return url;
}
Je ne vois pas de problèmes majeurs avec une solution regex. Mais n'oubliez pas de conserver l'identifiant du fragment (texte après le #
).
Voici ma solution:
function RemoveParameterFromUrl(url, parameter) {
return url
.replace(new RegExp('[?&]' + parameter + '=[^&#]*(#.*)?$'), '$1')
.replace(new RegExp('([?&])' + parameter + '=[^&]*&'), '$1');
}
Et pour répondre à votre question, oui, il vous faudrait échapper des caractères .
dans les noms de paramètres.
Toute personne intéressée par une solution regex, j'ai mis en place cette fonction pour ajouter/supprimer/mettre à jour un paramètre de chaîne de requête. Ne pas fournir de valeur va supprimer le paramètre, en fournir une ajoutera/mettra à jour le paramètre. Si aucune URL n'est fournie, elle sera extraite de window.location. Cette solution prend également en compte l'ancre de l'URL.
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;
}
}
METTRE À JOUR
Il y avait un bogue lors de la suppression du premier paramètre de la chaîne de requête, j'ai retravaillé la regex et testé pour inclure un correctif.
MISE À JOUR 2
@schellmax met à jour pour corriger la situation où le symbole de hashtag est perdu lors de la suppression d'une variable de chaîne de requête directement avant un hashtag
Les navigateurs modernes fournissent URLSearchParams
interface pour travailler avec les paramètres de recherche. Qui a delete
méthode qui supprime param par son nom.
if (typeof URLSearchParams !== 'undefined') {
const params = new URLSearchParams('param1=1¶m2=2¶m3=3')
console.log(params.toString())
params.delete('param2')
console.log(params.toString())
} else {
console.log(`Your browser ${navigator.appVersion} does not support URLSearchParams`)
}
En supposant que vous souhaitiez supprimer le paramètre key = val de l'URI:
function removeParam(uri) {
return uri.replace(/([&\?]key=val*$|key=val&|[?&]key=val(?=#))/, '');
}
Voici une fonction complète pour l’ajout et la suppression de paramètres basés sur cette question et ce github Gist: https://Gist.github.com/excalq/2961415
var updateQueryStringParam = function (key, value) {
var baseUrl = [location.protocol, '//', location.Host, location.pathname].join(''),
urlQueryString = document.location.search,
newParam = key + '=' + value,
params = '?' + newParam;
// If the "search" string exists, then build params from it
if (urlQueryString) {
updateRegex = new RegExp('([\?&])' + key + '[^&]*');
removeRegex = new RegExp('([\?&])' + key + '=[^&;]+[&;]?');
if( typeof value == 'undefined' || value == null || value == '' ) { // Remove param if value is empty
params = urlQueryString.replace(removeRegex, "$1");
params = params.replace( /[&;]$/, "" );
} else if (urlQueryString.match(updateRegex) !== null) { // If param exists already, update it
params = urlQueryString.replace(updateRegex, "$1" + newParam);
} else { // Otherwise, add it to end of query string
params = urlQueryString + '&' + newParam;
}
}
window.history.replaceState({}, "", baseUrl + params);
};
Vous pouvez ajouter des paramètres comme ceci:
updateQueryStringParam( 'myparam', 'true' );
Et supprimez-le comme ceci:
updateQueryStringParam( 'myparam', null );
Dans ce fil, beaucoup ont dit que l'expression rationnelle n'était probablement pas la meilleure solution/stable ... donc je ne suis pas sûr à 100% si cette chose a des défauts, mais dans la mesure où je l'ai testée, cela fonctionne plutôt bien.
Vous pouvez changer l'URL avec:
window.history.pushState({}, document.title, window.location.pathname);
de cette façon, vous pouvez écraser l'URL sans le paramètre de recherche, je l'utilise pour nettoyer l'URL après avoir pris les paramètres GET.
La version ci-dessus en fonction
function removeURLParam(url, param)
{
var urlparts= url.split('?');
if (urlparts.length>=2)
{
var prefix= encodeURIComponent(param)+'=';
var pars= urlparts[1].split(/[&;]/g);
for (var i=pars.length; i-- > 0;)
if (pars[i].indexOf(prefix, 0)==0)
pars.splice(i, 1);
if (pars.length > 0)
return urlparts[0]+'?'+pars.join('&');
else
return urlparts[0];
}
else
return url;
}
Utilisation de jQuery:
function removeParam(key) {
var url = document.location.href;
var params = url.split('?');
if (params.length == 1) return;
url = params[0] + '?';
params = params[1];
params = params.split('&');
$.each(params, function (index, value) {
var v = value.split('=');
if (v[0] != key) url += value + '&';
});
url = url.replace(/&$/, '');
url = url.replace(/\?$/, '');
document.location.href = url;
}
Vous devriez utiliser une bibliothèque pour manipuler les adresses URI, car il est plus compliqué qu'il n'y paraît à la surface de le faire vous-même. Jetez un oeil à: http://medialize.github.io/URI.js/
Toutes les réponses sur ce fil ont un défaut en ce qu'elles ne préservent pas les parties d'ancrage/fragment des URL.
Donc, si votre URL ressemble à:
http://dns-entry/path?parameter=value#fragment-text
et vous remplacez 'paramètre'
vous allez perdre votre fragment de texte.
Ce qui suit est une adaptation des réponses précédentes (bobince via LukePH) qui résout ce problème:
function removeParameter(url, parameter)
{
var fragment = url.split('#');
var urlparts= fragment[0].split('?');
if (urlparts.length>=2)
{
var urlBase=urlparts.shift(); //get first part, and remove from array
var queryString=urlparts.join("?"); //join it back up
var prefix = encodeURIComponent(parameter)+'=';
var pars = queryString.split(/[&;]/g);
for (var i= pars.length; i-->0;) { //reverse iteration as may be destructive
if (pars[i].lastIndexOf(prefix, 0)!==-1) { //idiom for string.startsWith
pars.splice(i, 1);
}
}
url = urlBase + (pars.length > 0 ? '?' + pars.join('&') : '');
if (fragment[1]) {
url += "#" + fragment[1];
}
}
return url;
}
Voici ce que j'utilise:
if (location.href.includes('?')) {
history.pushState({}, null, location.href.split('?')[0]);
}
URL d'origine: http://www.example.com/test/hello?id=123&foo=bar
URL de destination: http://www.example.com/test/hello
D'après ce que je peux voir, rien de ce qui précède ne peut gérer les paramètres normaux et les paramètres de tableau. En voici un qui fait.
function removeURLParameter(param, url) {
url = decodeURI(url).split("?");
path = url.length == 1 ? "" : url[1];
path = path.replace(new RegExp("&?"+param+"\\[\\d*\\]=[\\w]+", "g"), "");
path = path.replace(new RegExp("&?"+param+"=[\\w]+", "g"), "");
path = path.replace(/^&/, "");
return url[0] + (path.length
? "?" + path
: "");
}
function addURLParameter(param, val, url) {
if(typeof val === "object") {
// recursively add in array structure
if(val.length) {
return addURLParameter(
param + "[]",
val.splice(-1, 1)[0],
addURLParameter(param, val, url)
)
} else {
return url;
}
} else {
url = decodeURI(url).split("?");
path = url.length == 1 ? "" : url[1];
path += path.length
? "&"
: "";
path += decodeURI(param + "=" + val);
return url[0] + "?" + path;
}
}
Comment l'utiliser:
url = location.href;
-> http://example.com/?tags[]=single&tags[]=promo&sold=1
url = removeURLParameter("sold", url)
-> http://example.com/?tags[]=single&tags[]=promo
url = removeURLParameter("tags", url)
-> http://example.com/
url = addURLParameter("tags", ["single", "promo"], url)
-> http://example.com/?tags[]=single&tags[]=promo
url = addURLParameter("sold", 1, url)
-> http://example.com/?tags[]=single&tags[]=promo&sold=1
Bien sûr, pour mettre à jour un paramètre, supprimez puis ajoutez. N'hésitez pas à créer une fonction fictive pour cela.
Une version modifiée de la solution par ssh_imov
function removeParam(uri, keyValue) {
var re = new RegExp("([&\?]"+ keyValue + "*$|" + keyValue + "&|[?&]" + keyValue + "(?=#))", "i");
return uri.replace(re, '');
}
Appelle comme ça
removeParam("http://google.com?q=123&q1=234&q2=567", "q1=234");
// returns http://google.com?q=123&q2=567
Ceci retourne l'URL sans TOUS les paramètres GET:
var href = document.location.href;
var search = document.location.search;
var pos = href.indexOf( search );
if ( pos !== -1 ){
href = href.slice( 0, pos );
console.log( href );
}
Il s'agit d'un paramètre de requête propre version remove avec la classe URL pour les navigateurs actuels:
function removeUrlParameter(url, paramKey)
{
var r = new URL(url);
r.searchParams.delete(paramKey);
return r.href;
}
URLSearchParams non pris en charge sur les anciens navigateurs
https://caniuse.com/#feat=urlsearchparams
IE, Edge (inférieur à 17) et Safari (inférieur à 10.3) ne prennent pas en charge URLSearchParams dans la classe d'URL.
Polyfills
URLSearchParams uniquement polyfill
https://github.com/WebReflection/url-search-params
Complétez les adresses URL et PolySearch de Polyfill pour correspondre aux dernières spécifications du WHATWG