Obtener la ubicación de hash de URL y usarla en jQuery

135

Me gustaría obtener el valor después de un hash en la URL de la página actual y luego poder aplicarlo en una nueva función ... por ejemplo.

La URL podría ser

www.example.com/index.html#foo

Y me gustaría usar esto junto con el siguiente código

$('ul#foo:first').show();

Estoy asumiendo / esperando que haya alguna forma de agarrar esto, y convertirlo en una variable que luego pueda usar en el segundo fragmento de código.

Robbie White
fuente
8
No tengo ningún código para ti, pero debes asegurarte de desinfectar la entrada, ya que esto parece adecuado para la inyección de código.
Nate B el
Comprender que esta pregunta tiene casi una década, 'ul#foo:first'no tiene sentido ya que las ID deben ser únicas, por lo tanto, agregar :firstal selector es redundante, a menos que esté duplicando ID que no es válido. Tenga en cuenta que incluso hace una década, las identificaciones repetidas aún no eran válidas.
j08691
Todavía estaba equivocado hace una década
Douglas

Respuestas:

280

Nota del editor: el siguiente enfoque tiene serias implicaciones de seguridad y, dependiendo de la versión de jQuery que esté utilizando, puede exponer a sus usuarios a ataques XSS. Para obtener más detalles, consulte la discusión sobre el posible ataque en los comentarios sobre esta respuesta o esta explicación en Security Stack Exchange .

Puede usar la location.hashpropiedad para obtener el hash de la página actual:

var hash = window.location.hash;
$('ul'+hash+':first').show();

Tenga en cuenta que esta propiedad ya contiene el #símbolo al principio.

En realidad no necesita el :firstpseudo-selector ya que está utilizando el selector de ID , se supone que las ID son únicas dentro del DOM.

En caso de que desee obtener el hash de una cadena URL, puede usar el String.substringmétodo:

var url = "http://example.com/file.htm#foo";
var hash = url.substring(url.indexOf('#')); // '#foo'

Consejo: Tenga en cuenta que el usuario puede cambiar el hash como quiera, inyectando cualquier cosa en su selector, debe verificar el hash antes de usarlo.

CMS
fuente
30
Tenga en cuenta que los selectores jQuery se pueden usar para ejecutar código javascript personalizado, por lo que el uso de hash no desinfectados es horriblemente inseguro. Hay una solución a medias para esto en las versiones recientes de jQuery para los selectores que contienen un # antes del código inyectado, pero aún está en riesgo si elimina la marca # desde el principio de location.hash. P.ej. var hash = location.hash.slice(1); $('ul.item'+hash).show().append($('#content'));esto ejecutará una etiqueta de script colocada en el hash. Es un buen hábito usar en $('body').find('ul'+hash+':first')lugar de $('ul'+hash+':first').
Tgr
40
Algunos navegadores devuelven el símbolo hash, y otros no, por lo que es más seguro usarlo:var hash = location.hash.replace('#', '');
Tim
12
Alice dirige un sitio web, Bob lo visita, se autentica y recibe una cookie de sesión. (Puede pasar algún tiempo aquí, Bob incluso puede cerrar su navegador.) Charlie le envía un correo a Bob diciendo "¡Mira este enlace genial!". Bob abre el enlace, que conduce a un sitio controlado por Charlie. La página redirige el navegador de Bob a una página en el sitio de Alice con una carga útil de ataque en el hash. La carga útil se ejecuta y, dado que el navegador aún recuerda las cookies, puede enviarlas a Charlie.
Tgr
2
@Tgr, gracias por elaborar y conectar los puntos. Este ejemplo concreto me hace (y espero que otros) más inclinados a la vigilancia para mantener las cosas seguras.
snapfractalpop
2
@buffer: $(userInput)generalmente no es seguro porque $está sobrecargado y puede buscar nodos existentes o crear nuevos dependiendo de si la cadena contiene <>caracteres. $(document).find(userInput)siempre buscará nodos existentes para que sea menos inseguro. Dicho esto, la mejor práctica es desinfectar siempre la entrada del usuario, por ejemplo, si usa identificadores alfanuméricos, asegúrese de que sea alfanumérico.
Tgr
35

location.hash no es seguro para IE , en el caso de IE (incluido IE9), si su página contiene iframe, luego de la actualización manual dentro del contenido del iframe, obtenga el valor location.hash es antiguo (valor para la primera carga de la página). mientras que el valor recuperado manualmente es diferente de location.hash, recuérdelo siempre a través de document.URL

var hash = document.URL.substr(document.URL.indexOf('#')+1) 
Deepak Patil
fuente
77
Actualización: document.URL no contiene valores hash en firefox 3.6, por lo que location.href es seguro var hash = location.href.substr (location.href.indexOf ('#') + 1)
Deepak Patil
4

Para aquellos que buscan una solución javascript pura

 document.getElementById(location.hash.substring(1)).style.display = 'block'

Espero que esto te ahorre algo de tiempo.

Matas Vaitkevicius
fuente
3

Desde jQuery 1.9, el :targetselector coincidirá con el hash de URL. Entonces podrías hacer:

$(":target").show(); // or $("ul:target").show();

Que seleccionaría el elemento con la ID que coincida con el hash y lo mostraría.

j08691
fuente
¿hay alguna manera de extraer el hash como una cadena en lugar de id de coincidencia?
Ina
@ina ¿Te refieres a obtener el hash de jQuery's :targetcomo una cadena? Si es así, no lo creo.
j08691
1

Sugeriría mejor cek primero si la página actual tiene un hash. De lo contrario lo será undefined.

$(window).on('load', function(){        
    if( location.hash && location.hash.length ) {
       var hash = decodeURIComponent(location.hash.substr(1));
       $('ul'+hash+':first').show();;
    }       
});
Chetabahana
fuente
1

Estoy usando esto para abordar las implicaciones de seguridad señaladas en la respuesta de @ CMS.

// example 1: www.example.com/index.html#foo

// load correct subpage from URL hash if it exists
$(window).on('load', function () {
    var hash = window.location.hash;
    if (hash) {
        hash = hash.replace('#',''); // strip the # at the beginning of the string
        hash = hash.replace(/([^a-z0-9]+)/gi, '-'); // strip all non-alphanumeric characters
        hash = '#' + hash; // hash now equals #foo with example 1

        // do stuff with hash
        $( 'ul' + hash + ':first' ).show();
        // etc...
    }
});
Squarecandy
fuente