Wie kann ich den Standort-Hash entfernen, ohne dass die Seite gescrollt wird?

77

Ist es möglich, den Hash zu entfernen, window.locationohne dass die Seite nach oben springt? Ich muss in der Lage sein, den Hash zu ändern, ohne Sprünge zu verursachen.

Ich habe das:

$('<a href="#123">').text('link').click(function(e) {
  e.preventDefault();
  window.location.hash = this.hash;
}).appendTo('body');

$('<a href="#">').text('unlink').click(function(e) {
  e.preventDefault();
  window.location.hash = '';
}).appendTo('body');

Siehe Live-Beispiel hier: http://jsbin.com/asobi

Wenn der Benutzer auf " Link " klickt, wird das Hash-Tag ohne Seitensprünge geändert, sodass dies einwandfrei funktioniert.

Wenn der Benutzer jedoch auf " Verknüpfung aufheben " klickt, wird das Has -Tag entfernt und die Seite springt nach oben. Ich muss den Hash ohne diese Nebenwirkung entfernen.

David Hellsing
quelle
Lassen Sie mich raten: Ihr Kunde findet den Hash hässlich und verschmutzt die nette und ansonsten saubere URL mit der Aufschrift: http: // www.example.com/ (ohne Leerzeichen)?
anddoutoi
Gute Vermutung, aber nein. Ich habe Lesezeichen modale Fenster basierend auf Hash-URLs, und wenn der Benutzer das Fenster schließt, muss der Hash gehen.
David Hellsing
1
Mir ist bewusst, dass diese Frage fast 2 Jahre alt ist, aber dieser Kommentar kann einem zukünftigen Leser helfen. Wenn Sie den Hash wirklich entfernen möchten, können Sie die URL mit history.pushState () ändern. developer.mozilla.org/en/DOM/…
mehrdeutige
@ Joshli, leider wird es nicht funktionieren IE9.
Tsukimoto Mitsumasa

Antworten:

97

Ich glaube, wenn Sie nur einen Dummy-Hash eingeben, wird dieser nicht gescrollt, da es keine Übereinstimmung gibt, zu der Sie scrollen können.

<a href="#A4J2S9F7">No jumping</a>

oder

<a href="#_">No jumping</a>

"#"an sich ist gleichbedeutend "_top"damit, dass ein Bildlauf zum Anfang der Seite erfolgt

scunliffe
quelle
12
Nicht optimal, aber gut genug. Ich habe '# /' mit dem gleichen Ergebnis verwendet.
David Hellsing
window.location.hash = (new_hash === '') ? '_' : new_hash;
Tester
Nicht zufrieden mit dieser Lösung, was ist mit: stackoverflow.com/questions/19728020/…
stephen
21
Ich benutzewindow.location.hash = "💩";
Aeyoun
37

Ich benutze das Folgende auf einigen Seiten, KEINE SEITENSPRÜCHE!

Schöne, saubere Adressleiste für HTML5-freundliche Browser und nur ein # für ältere Browser.

$('#logo a').click(function(e){
    window.location.hash = ''; // for older browsers, leaves a # behind
    history.pushState('', document.title, window.location.pathname); // nice and clean
    e.preventDefault(); // no page reload
});
neokio
quelle
12
history.replaceStateDies ist möglicherweise vorzuziehen, da durch Drücken von Zurück zur letzten gültigen URL zurückgekehrt wird.
Orlade
Es sollte auch beachtet werden, dass dieser Code zwei Änderungen am Navigationsverlauf vornimmt. Das Ergebnis ist, dass der Benutzer, wenn er die Zurück-Taste drückt, zuerst durch [url] # geleitet wird und dann einen zweiten Klick benötigt, um auf der [url] ohne # zu landen. Wenn Sie die Back-Button-Erfahrung entwickeln, sollten Sie einen bedingten Ansatz in Betracht ziehen, um den Status nicht zweimal festzulegen.
Vinney Kelly
18

Die Hash-Eigenschaft von window.location ist in vielerlei Hinsicht dumm. Dies ist einer von ihnen; Das andere ist, dass es unterschiedliche Werte zum Abrufen und Festlegen hat:

window.location.hash = "hello";  // url now reads *.com#hello
alert(window.location.hash);   // shows "#hello", which is NOT what I set.
window.location.hash = window.location.hash; // url now reads *.com##hello

Beachten Sie, dass durch Setzen der Hash-Eigenschaft auf '' auch die Hash-Markierung entfernt wird. Das ist es, was die Seite umleitet. Um den Wert des Hash-Teils der URL auf '' zu setzen, die Hash-Markierung zu belassen und daher nicht zu aktualisieren, schreiben Sie Folgendes:

window.location.href = window.location.href.replace(/#.*$/, '#');

Es gibt keine Möglichkeit, die einmal gesetzte Raute vollständig zu entfernen, ohne die Seite zu aktualisieren.

UPDATE 2012:

Wie Blazemonger und thinkdj hervorgehoben haben, hat sich die Technologie verbessert. In einigen Browsern können Sie dieses Hashtag löschen, in anderen nicht. Versuchen Sie Folgendes, um beide zu unterstützen:

if ( window.history && window.history.pushState ) { 
    window.history.pushState('', '', window.location.pathname) 
} else { 
    window.location.href = window.location.href.replace(/#.*$/, '#'); 
}
Olooney
quelle
2
Nicht wahr. Mit Browsern, die dies unterstützen window.history, können Sie genau dies tun.
Blazemonger
@Blazemonger Stimmt das! Sie können einen history.pushState ('', document.title, window.location.pathname) verwenden.
Deepak Thomas
Andererseits wurde dieser Kommentar im Februar 10 abgegeben und die Browser begannen Mitte 2011, Pushstates zu unterstützen
Deepak Thomas
Der obige Code behält die Abfragezeichenfolge nicht bei. Verwenden Siewindow.history.pushState('', '', window.location.pathname + window.location.search);
dipole_moment
3

Dies ist ein alter Beitrag, aber ich wollte meine Lösung teilen. Alle Links in meinem Projekt, die von JS verarbeitet werden, haben das Attribut href = "#_ js" (oder einen beliebigen Namen, den Sie nur für diese Zwecke verwenden möchten) und die Seiteninitialisierung Ich mache:

$('body').on('click.a[href="#_js"]', function() {
    return false;
});

Das wird den Trick machen

Tomer Gal
quelle
2

Wenn Sie window.location.hash auf einen leeren oder nicht vorhandenen Ankernamen setzen, wird die Seite immer gezwungen, nach oben zu springen. Die einzige Möglichkeit, dies zu verhindern, besteht darin, die Bildlaufposition des Fensters zu erfassen und nach dem Hash-Wechsel wieder auf diese Position zu setzen.

Dadurch wird auch ein Neulackieren der Seite erzwungen (kann nicht vermieden werden). Da sie jedoch in einem einzelnen js-Prozess ausgeführt wird, springt sie (theoretisch) nicht nach oben / unten.

$('<a href="#123">').text('link').click(function(e) {
    e.preventDefault();
    window.location.hash = this.hash;
}).appendTo('body');

$('<a href="#">').text('unlink').click(function(e) {
    e.preventDefault();
    var pos = $(window).scrollTop(); // get scroll position
    window.location.hash = '';
    $(window).scrollTop(pos); // set scroll position back
}).appendTo('body');

Hoffe das hilft.

BGerrissen
quelle
1
Nicht ganz korrekt ... Wenn Sie den Hash auf "" setzen, wird nach oben gescrollt. Wenn jedoch kein benannter Anker oder Element mit einem übereinstimmenden idAttribut vorhanden ist, wird der Browser nicht gescrollt.
Scunliffe
1

Ich bin mir nicht sicher, ob dies zum gewünschten Ergebnis führt. Probieren Sie es aus:

$('<a href="#">').text('unlink').click(function(e) {
    e.preventDefault();
    var st = parseInt($(window).scrollTop())
    window.location.hash = '';
    $('html,body').css( { scrollTop: st });  
});

Speichern Sie grundsätzlich den Bildlaufversatz und stellen Sie ihn wieder her, nachdem Sie den leeren Hash zugewiesen haben.

Tom Bartel
quelle
1
es funktioniert für mich, außer ich benutze $(window).scrollTop(st)anstelle von.css()
Thomas Joulin
Versuchte diesen, da ich brauche den Hash zu einem vorhandenen #id zu ändern. Alles funktioniert gut, aber wenn ich versuche, mit der Maus zu scrollen, springt der Bildlauf nach dem Ändern des Hash auf Null. Irgendwelche Ideen, was dies verursachen könnte?
Lucascaro
1

Haben Sie es return false;im Event-Handler versucht ? jQuery macht etwas Besonderes, wenn Sie das tun, ähnlich, aber AFAIK wirkungsvoller als e.preventDefault.

Roman Nurik
quelle
2
return false;in jQuery und in nativen Ereignishandlern in kompatiblen Browsern entspricht e.preventDefault(); e.stopPropagation();. Ich denke nicht, dass das Stoppen der Verbreitung bei diesem Problem helfen wird.
Jesse Hallett
0

Hoffe das hilft

html

<div class="tabs">
  <ul>
    <li><a href="#content1">Tab 1</a></li>
    <li><a href="#content2">Tab 2</a></li>
    <li><a href="#content3">Tab 3</a></li>
  </ul>
</div>
<div class="content content1">
    <p>1. Content goes here</p>
</div>
<div class="content content2">
    <p>2. Content goes here</p>
</div>
<div class="content content3">
    <p>3. Content goes here</p>
</div>

js

function tabs(){
  $(".content").hide();

  if (location.hash !== "") {
    $('.tabs ul li:has(a[href="' + location.hash + '"])').addClass("active");
    var hash = window.location.hash.substr(1);
    var contentClass = "." + hash;
    $(contentClass).fadeIn();
  } else {
    $(".tabs ul li").first().addClass("active");
    $('.tabs').next().css("display", "block");
  }
}
tabs();

$(".tabs ul li").click(function(e) {
  $(".tabs ul li").removeAttr("class");
  $(this).addClass("active");
  $(".content").hide();
  var contentClass = "." + $(this).find("a").attr("href").substr(1);
  $(contentClass).fadeIn();
  window.location.hash = $(this).find("a").attr("href");
  e.preventDefault();
  return false;
});

URL ohne Hash.
http://output.jsbin.com/tojeja

URL mit Hashtag, die nicht zum Anker springt.
http://output.jsbin.com/tojeja#content1

Shak Daniel
quelle