Это потому, что вы только проверяете, имеет ли якорь значение hash
, установленное в href
, в то время как вам также необходимо проверить, действительно ли якорь указывает на текущий документ.
Это может быть легко достигается путем построения пути вашего якоря без ха sh:
// builds an URL path without the hash
function buildPath( url ) {
return url.origin + url.pathname + url.search;
}
и сравнения его с указанным в вашем документе. Обратите внимание, что вы не можете использовать window.location
, потому что ваши HTML якоря будут использовать это не как baseURI , а как значение document.baseURI
, которое можно изменить, например, с помощью <base>
element.
Итак, нам нужно создать новый экземпляр URL из этого базового URI:
const doc_URI = new URL( document.baseURI );
И мы готовы к go:
document.onclick = (evt) => {
const target = evt.target;
if( target.matches( 'a' ) ) {
evt.preventDefault();
const doc_URI = new URL( document.baseURI );
const is_valid_anchor = target.hash !== "" &&
buildPath( target ) === buildPath( doc_URI );
console.log( 'is valid', is_valid_anchor );
}
};
// builds an URL path without the hash
function buildPath( url ) {
return url.origin + url.pathname + url.search;
}
a { display: block; }
<a href="#foo">"#foo" (same)</a>
<a href="/some-other-page/#foo">"/some-other-page/#foo" (different)</a>
<a href="?bar=baz#foo">"?bar=baz#foo" (different)</a>
<a href="">"" (different)</a>
<a href="https://stacksnippets.net/js#foo">"https://stacksnippets.net/js#foo" (same)</a>
<a href="http://stacksnippets.net/js#foo">"http://stacksnippets.net/js#foo" (different)</a>
Так в вашем коде это даст
$("a").on('click', function(event) {
// Make sure this.hash has a value before overriding default behavior
// And that it points to the current document
var doc_URI = new URL( document.baseURI );
if (this.hash !== "" && buildPath( this ) === buildPath( doc_URI )) {
// the rest of your code