Obter valores de URL dos parâmetros da string de consulta com jQuery / Javascript (querystring)

149

Alguém conhece uma boa maneira de escrever uma extensão jQuery para lidar com parâmetros de string de consulta? Basicamente, quero estender a ($)função mágica do jQuery para que eu possa fazer algo assim:

$('?search').val(); 

Que me daria o "teste" valor na seguinte URL: http://www.example.com/index.php?search=test.

Eu já vi muitas funções que podem fazer isso no jQuery e Javascript, mas na verdade eu quero estender o jQuery para funcionar exatamente como é mostrado acima. Não estou procurando um plugin jQuery, estou procurando uma extensão para o método jQuery.

TroySteven
fonte
4
Perguntado e respondido: stackoverflow.com/questions/901115/…
Nico Westerdale 11/11
1
@NicoWesterdale - Eu passei por esse link, mas não vi nenhuma resposta que resolvesse essa pergunta em particular. Ele disse que quer exatamente como acima.
mrtsherman
2
Eu não acho que você pode fazer isso, uma sequência passada é analisada pelo sizzler e depois resolvida para uma matriz de objetos DOM. Você pode estender o correspondente para fornecer filtros personalizados, mas não pode ter um objeto jquery com base em uma sequência.
Andrew
6
Não está $sobrecarregado o suficiente?
Quentin
1
@mrtsherman Veja a função getParameterByName () no link que forneci. Não, você não pode fazê-lo diretamente dentro de um prompt $, mas não é para isso que servem os seletores jQuery. Ele está apenas selecionando parte de uma string de URL, não tentando acessar parte do DOM, que é o que $ () faz. É uma coisa totalmente diferente. Se você realmente quisesse usar o jQuery, poderia escrever um plugin que usasse esta sintaxe: $ .getParameterByName (param), há um exemplo mais abaixo na página que eu vinculei a ele que faz exatamente isso. Meio inútil embora.
Nico Westerdale

Respostas:

46

Após anos de análise feia de strings, existe uma maneira melhor: URLSearchParams Vamos dar uma olhada em como podemos usar essa nova API para obter valores a partir do local!

// Supondo "? Post = 1234 & action = edit"

var urlParams = new URLSearchParams(window.location.search);
console.log(urlParams.has('post')); // true
console.log(urlParams.get('action')); // "edit"
console.log(urlParams.getAll('action')); // ["edit"]
console.log(urlParams.toString()); // "?post=1234&action=edit"
console.log(urlParams.append('active', '1')); // "?

post=1234&action=edit&active=1"

UPDATE: IE não é suportado

use esta função a partir de uma resposta abaixo, em vez de URLSearchParams

$.urlParam = function (name) {
    var results = new RegExp('[\?&]' + name + '=([^&#]*)')
                      .exec(window.location.search);

    return (results !== null) ? results[1] || 0 : false;
}

console.log($.urlParam('action')); //edit
Saurin
fonte
1
O URLSearchParams é suportado por todos os navegadores?
divino
Opa! ohh cara, o IE não é suportado !! Acabei de testar. Embora o Chrome, o FF, o Safari não tenha problemas.
Saurin
1
@divine - Há uma polyfill para URLSearchParams aqui: github.com/WebReflection/url-search-params
Roberto
Se você adicionar um polyfill para navegadores não suportados, esta solução URLSearchParams funcionará bem. github.com/ungap/url-search-params
Louisvdw
104

Por que estender o jQuery? Qual seria o benefício de estender o jQuery contra apenas ter uma função global?

function qs(key) {
    key = key.replace(/[*+?^$.\[\]{}()|\\\/]/g, "\\$&"); // escape RegEx meta chars
    var match = location.search.match(new RegExp("[?&]"+key+"=([^&]+)(&|$)"));
    return match && decodeURIComponent(match[1].replace(/\+/g, " "));
}

http://jsfiddle.net/gilly3/sgxcL/

Uma abordagem alternativa seria analisar toda a cadeia de consulta e armazenar os valores em um objeto para uso posterior. Essa abordagem não requer uma expressão regular e estende o window.locationobjeto (mas, poderia facilmente usar uma variável global):

location.queryString = {};
location.search.substr(1).split("&").forEach(function (pair) {
    if (pair === "") return;
    var parts = pair.split("=");
    location.queryString[parts[0]] = parts[1] &&
        decodeURIComponent(parts[1].replace(/\+/g, " "));
});

http://jsfiddle.net/gilly3/YnCeu/

Esta versão também utiliza Array.forEach(), que não está disponível nativamente no IE7 e IE8. Ele pode ser adicionado usando a implementação no MDN ou você pode usar o jQuery $.each().

gilly3
fonte
2
Não é comum, mas é válido usar ponto-e-vírgula em vez de e comercial nos parâmetros da consulta.
Muhd
@ Muhd ​​- É "válido" usar qualquer delimitador que você gosta em uma string de consulta, desde que o seu código o compreenda. Mas, quando um formulário é enviado, os campos do formulário são enviados como name=valuepares, separados por &. Se o seu código estiver usando um formato de string de consulta personalizado, obviamente, você precisará escrever um analisador de string de consulta personalizado sempre que a string de consulta for consumida, seja no servidor ou no cliente.
gilly3
2
@nick - Interessante. Mas sua sugestão para os servidores HTTP tratarem ponto-e-vírgula como e comercial serve apenas para tornar o HTML mais bonito ao usar um link para imitar o envio de um formulário. É apenas uma sugestão e não é padrão. Um GETenvio de formulário padrão é codificado como application/x-www-form-urlencoded, com valores separados por &. Meu código lida com esse padrão. As estruturas de URL personalizadas, como a que você vinculou, precisarão de um analisador personalizado do lado do servidor e do cliente. Independentemente disso, adicionar essa capacidade ao meu código acima seria trivial.
gilly3
1
@illy de fato - se você quer código portátil, precisa suportar os dois #
nick
1
Adicione "i" ao RegExp () para que a chave não faça distinção entre maiúsculas e minúsculas: new RegExp ("[? &]" + Key + "= ([^ &] +) (& | $)", "i"));
Yovav
94

JQuery O plugin jQuery-URL-Parser faz o mesmo trabalho, por exemplo, para recuperar o valor do parâmetro de string de consulta de pesquisa , você pode usar

$.url().param('search');

Esta biblioteca não é mantida ativamente. Como sugerido pelo autor do mesmo plugin, você pode usar URI.js .

Ou você pode usar o js-url . É bem parecido com o abaixo.

Para que você possa acessar o parâmetro de consulta como $.url('?search')

RameshVel
fonte
2
Agradável. E o código é de domínio público, assim você não precisa nem incluir os comentários.
Muhd
4
Boa solução, mas não funcionará se você estiver testando via arquivo: /
kampsj
1
O que é que têm de fazer qualquer coisa com, @kampsj
RameshVel
3
Olá @kampsj, testar com file://protocolo fará com que muito mais coisas não funcionem. Você pode criar um servidor HTML estático muito rápido e fácil com o node.js. stackoverflow.com/questions/16333790/…
Jess
2
Este plugin não é mais mantido e o próprio autor está sugerindo o uso de outros plugins.
JanErikGunnar 16/10
77

Encontrei esta jóia de nossos amigos no SitePoint. https://www.sitepoint.com/url-parameters-jquery/ .

Usando o jQuery PURE. Eu apenas usei isso e funcionou. Ajustou um pouco, por exemplo, saquê.

//URL is http://www.example.com/mypage?ref=registration&[email protected]

$.urlParam = function (name) {
    var results = new RegExp('[\?&]' + name + '=([^&#]*)')
                      .exec(window.location.search);

    return (results !== null) ? results[1] || 0 : false;
}

console.log($.urlParam('ref')); //registration
console.log($.urlParam('email')); //[email protected]

Use como quiser.

ClosDesign
fonte
Ótimo. Obrigado! Acho que você não precisa da última chave de fechamento.
bhtabor
Ahh sim, você está correto. Editou a postagem. Isso foi deixado de alguma declaração if no meu código. Obrigado.
ClosDesign
1
Você deve usar window.location.search em vez de .href - caso contrário, é bom.
precisa saber é o seguinte
4
Em vez de results[1] || 0, você deve fazer se (resultados) {retornar resultados [1]} retornar 0; Os parâmetros de consulta do bcoz podem não estar presentes. E a modificação lidará com todos os casos genéricos.
myDoggyWritesCode
1
O que você faz se tiver algo parecido https://example.com/?c=Order+ID? Esse sinal de adição ainda permanece nesta função.
Volomike
47

Este não é meu exemplo de código, mas eu o usei no passado.

//First Add this to extend jQuery

    $.extend({
      getUrlVars: function(){
        var vars = [], hash;
        var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
        for(var i = 0; i < hashes.length; i++)
        {
          hash = hashes[i].split('=');
          vars.push(hash[0]);
          vars[hash[0]] = hash[1];
        }
        return vars;
      },
      getUrlVar: function(name){
        return $.getUrlVars()[name];
      }
    });

    //Second call with this:
    // Get object of URL parameters
    var allVars = $.getUrlVars();

    // Getting URL var by its name
    var byName = $.getUrlVar('name');
Rob Nield
fonte
2
Você não deve dividir em '='; tecnicamente, é bom ter um segundo sinal de igual no valor de qualquer par de chave / valor. - Somente o primeiro sinal de igual que você encontrar (por par de chave / valor) deve ser tratado como um delimitador. (Além disso, o sinal de igual não é estritamente necessário, é possível ter uma chave com nenhum valor.)
BrainSlugs83
Solução limpa. Funcionou perfeitamente no meu caso.
JF Gagnon
$ .extend ({getUrlVars: function () {var vars = [], hash; var hashes = window.location.href.slice (window.location.href.indexOf ('?') + 1) .split ('& '); for (var i = 0; i <hashes.length; i ++) {hash = hashes [i] .split (' = '); var k = hash.shift (); vars.push (k); vars [k] = hash.join ("");} retorna vars;}, getUrlVar: function (nome) {retorna $ .getUrlVars () [nome];}});
Mupinc 27/04
15

Eu escrevi uma pequena função em que você só precisa analisar o nome do parâmetro de consulta. Portanto, se você possui:? Project = 12 & Mode = 200 & date = 27-05-2013 e deseja o parâmetro 'Mode', basta analisar o nome do 'Mode' na função:

function getParameterByName( name ){
    var regexS = "[\\?&]"+name+"=([^&#]*)", 
  regex = new RegExp( regexS ),
  results = regex.exec( window.location.search );
  if( results == null ){
    return "";
  } else{
    return decodeURIComponent(results[1].replace(/\+/g, " "));
  }
}

// example caller:
var result =  getParameterByName('Mode');
Plippie
fonte
Se o seu nome não tem lixo, você pode soltar o primeiro regex e faz mais sentido para começar a partir location.search
mplungjan
7

Com base na resposta do @Rob Neild acima, aqui está uma adaptação JS pura que retorna um objeto simples de parâmetros de string de consulta decodificados (sem% 20, etc).

function parseQueryString () {
  var parsedParameters = {},
    uriParameters = location.search.substr(1).split('&');

  for (var i = 0; i < uriParameters.length; i++) {
    var parameter = uriParameters[i].split('=');
    parsedParameters[parameter[0]] = decodeURIComponent(parameter[1]);
  }

  return parsedParameters;
}

fonte
Não vi nenhum erro ao usar este código. Qual navegador você está usando? Eu testei com o Firefox, Chrome e Safari atuais.
Sim, desculpe, eu li errado. Eu pensei ter visto chamar um método em algo que estava retornando indefinido. Então, na verdade, está apenas rodando uma vez quando não é necessário. Quando a pesquisa é "". E você obtém {"": "undefined"}
Jerinaw
Sim. Provavelmente isso poderia ser refinado.
1

Escrito em Javascript Vanilla

     //Get URL
     var loc = window.location.href;
     console.log(loc);
     var index = loc.indexOf("?");
     console.log(loc.substr(index+1));
     var splitted = loc.substr(index+1).split('&');
     console.log(splitted);
     var paramObj = [];
     for(var i=0;i<splitted.length;i++){
         var params = splitted[i].split('=');
         var key = params[0];
         var value = params[1];
         var obj = {
             [key] : value
         };
         paramObj.push(obj);
         }
    console.log(paramObj);
    //Loop through paramObj to get all the params in query string.
Manas Prasad
fonte
1
function parseQueryString(queryString) {
    if (!queryString) {
        return false;
    }

    let queries = queryString.split("&"), params = {}, temp;

    for (let i = 0, l = queries.length; i < l; i++) {
        temp = queries[i].split('=');
        if (temp[1] !== '') {
            params[temp[0]] = temp[1];
        }
    }
    return params;
}

Eu uso isso.

donvercety
fonte