Window.location.hash dosyasını belgeyi atlamadan nasıl güncelleyebilirim?


163

Web sitemde bir sürgülü panel var.

Animasyon bittiğinde, hash'i böyle ayarladım

function() {
   window.location.hash = id;
}

(bu bir geri aramadır ve iddaha önce atanır).

Bu, kullanıcının panele yer işareti koymasına ve ayrıca JavaScript olmayan sürümün çalışmasına izin vermek için iyi çalışır.

Ancak, karmayı güncellediğimde, tarayıcı konuma atlar. Sanırım bu beklenen bir davranış.

Sorum şu: bunu nasıl önleyebilirim? Yani nasıl pencerenin karma değiştirebilirsiniz ancak değil hash varsa elemana tarayıcı kaydırma var? Bir tür event.preventDefault()şey mi?

JQuery 1.4 ve scrollTo eklentisini kullanıyorum .

Çok teşekkürler!

Güncelleme

İşte paneli değiştiren kod.

$('#something a').click(function(event) {
    event.preventDefault();
    var link = $(this);
    var id = link[0].hash;

    $('#slider').scrollTo(id, 800, {
        onAfter: function() {

            link.parents('li').siblings().removeClass('active');
            link.parent().addClass('active');
            window.location.hash = id;

            }
    });
});

2
Sanırım denediniz event.preventDefault():)
Marko

@ Marko Nereye yerleştireceğimi bilmiyorum!
alex

Kodunuzun geri kalanını gönderebilir misiniz?
Marko

@Marko Ivanovski İlgili olduğunu düşünmüyorum, ama ne yapabileceğimi göreceğim.
alex

3
@Gareth Bunun için bir yer olduğunu düşünmüyorum, çünkü karmayı güncellediğimde olur.
alex

Yanıtlar:


261

Eski API'larda yedekli modern tarayıcılarda geçmiş API'sini kullanarak bir çözüm vardır:

if(history.pushState) {
    history.pushState(null, null, '#myhash');
}
else {
    location.hash = '#myhash';
}

Kredi Lea Verou'ya gidiyor


Bence bu daha iyi bir yanıt.
Greg Annandale

10
PushState'in tarayıcı geçmişi yığınına durum ekleme yan (girintili) etkisi olduğunu unutmayın. Diğer bir deyişle, kullanıcı geri düğmesini tıkladığında, bir popstate olay dinleyicisi de eklemezseniz hiçbir şey olmaz.
David Cook

32
@DavidCook - history.replaceStateBir popstateolay dinleyicisine duyulan ihtiyacı önlemek için (karma değişiklikler için daha anlamlı olabilir) de kullanabiliriz .
Jack

Bu benim için çalıştı. Tarih değişikliğinin etkisini seviyorum. Bunun hashchangeolayı tetiklemeyeceği uyarısını eklemek istiyorum . Etrafta çalışmak zorunda olduğum bir şeydi.
Ürdün

uyarı! bu bir hashchangeolayı tetiklemeyecek
santiago arizti

52

Sorun window.location.hash öğesini bir öğenin ID özelliğine ayarlamanızdır. Tarayıcının, "preventDefault ()" yönteminden bağımsız olarak, bu öğeye atlaması beklenen davranıştır.

Bu sorunu aşmanın bir yolu, karma değerini şu şekilde rastgele bir değerle önek olarak eklemektir:

window.location.hash = 'panel-' + id.replace('#', '');

Ardından, tek yapmanız gereken sayfa yüklemesinde önceden eklenmiş karma değerini kontrol etmektir. Ek bir bonus olarak, şimdi karma değerini kontrol ettiğiniz için ona düzgün bir kaydırma yapabilirsiniz ...

$(function(){
    var h = window.location.hash.replace('panel-', '');
    if (h) {
        $('#slider').scrollTo(h, 800);
    }
});

Her zaman çalışmak için buna ihtiyacınız varsa (ve sadece ilk sayfa yüklemesinde değil), karma değerindeki değişiklikleri izlemek ve anında doğru öğeye atlamak için bir işlev kullanabilirsiniz:

var foundHash;
setInterval(function() {
    var h = window.location.hash.replace('panel-', '');
    if (h && h !== foundHash) {
        $('#slider').scrollTo(h, 800);
        foundHash = h;
    }
}, 100);

2
Bu aslında soruyu cevaplayan
zıplamadan

Bu, varsayılan tarayıcı davranışına göre atlamadan kaçınmak için karma için rastgele değerin eklenmesini ve silinmesini açıklayan soruyu gerçekten cevaplar.
lowtechsun

1
iyi bir çözümdür, ancak yer imi bölümlerinin kullanımını reddettiği için OP çözümünü zayıflatır
Samus

27

Ucuz ve kötü bir çözüm .. Çirkin # kullanın! tarzı.

Ayarlamak için:

window.location.hash = '#!' + id;

Okumak için:

id = window.location.hash.replace(/^#!/, '');

Sayfada eşleşmediği ve tutturmadığı veya kimliğe eklenmediği için atlama yapmaz.


3
IE 7 ve sitenin bazı mobil sürümleriyle uyumluluğu korumak zorunda kaldım. Bu çözüm benim için en temizdi. Genellikle pushState çözümlerinin her yerinde olurdum.
Eric Goodwin

1
ile karma ayarı: window.location.hash = '#/' + id;: o zaman ve ile değiştirilmesi window.location.hash.replace(/^#\//, '#');-> biraz url prettify olacak projects/#/tab1
braitsch

13

Neden geçerli kaydırma konumunu almıyorsunuz, bir değişkene koyup karmayı atayın ve sayfa kaydırmasını olduğu yere geri koyun:

var yScroll=document.body.scrollTop;
window.location.hash = id;
document.body.scrollTop=yScroll;

bu çalışmalı


1
hm, bu benim için bir süre için çalışıyordu, ama son birkaç ay içinde bazen bu firefox üzerinde çalışmayı durdurdu ....
matchew

10

Modern tarayıcılar için Attila Fulop (Lea Verou) ve eski tarayıcılar için Gavin Brock çözümünün bir kombinasyonunu aşağıdaki gibi kullandım:

if (history.pushState) {
    // IE10, Firefox, Chrome, etc.
    window.history.pushState(null, null, '#' + id);
} else {
    // IE9, IE8, etc
    window.location.hash = '#!' + id;
}

Gavin Brock tarafından gözlemlendiği gibi, kimliği geri yakalamak için dizeyi (bu durumda "!" Olabilir veya olmayabilir) aşağıdaki gibi tedavi etmeniz gerekir:

id = window.location.hash.replace(/^#!?/, '');

Bundan önce, user706270 tarafından önerilene benzer bir çözüm denedim, ancak Internet Explorer ile iyi çalışmadı: Javascript motoru çok hızlı olmadığından, kötü bir görsel efekt üreten kaydırma artışını ve azalmasını fark edebilirsiniz.


2

Bu çözüm benim için çalıştı.

Ayarla ilgili sorun location.hash, sayfada sayfada bulunması durumunda sayfanın bu kimliğe atlamasıdır.

Sorun window.history.pushState, kullanıcının tıkladığı her sekme için geçmişe bir girdi eklemesidir. Ardından kullanıcı backdüğmeyi tıklattığında önceki sekmeye gider. (istediğin bu olabilir ya da olmayabilir. İstediğim bu değildi).

Benim için, replaceStatesadece geçerli geçmişin yerini alması daha iyi bir seçimdi, bu yüzden kullanıcı backdüğmeyi tıkladığında bir önceki sayfaya giderler.

$('#tab-selector').tabs({
  activate: function(e, ui) {
    window.history.replaceState(null, null, ui.newPanel.selector);
  }
});

MDN'deki Geçmiş API'sı belgelerine göz atın .


1

Orijinal öğeyi değiştirip değiştiremeyeceğinizden emin değilim ama id attr komutunu data-id gibi başka bir şeye kullanmaya ne dersiniz? Daha sonra hash değeriniz için data-id değerini okursanız, atlamaz.


1

Bu çözüm benim için çalıştı

// store the currently selected tab in the hash value
    if(history.pushState) {
        window.history.pushState(null, null, '#' + id);
    }
    else {
        window.location.hash = id;
    }

// on load of the page: switch to the currently selected tab
var hash = window.location.hash;
$('#myTab a[href="' + hash + '"]').tab('show');

Ve tam js kodum

$('#myTab a').click(function(e) {
  e.preventDefault();
  $(this).tab('show');
});

// store the currently selected tab in the hash value
$("ul.nav-tabs > li > a").on("shown.bs.tab", function(e) {
  var id = $(e.target).attr("href").substr(1);
    if(history.pushState) {
        window.history.pushState(null, null, '#' + id);
    }
    else {
        window.location.hash = id;
    }
   // window.location.hash = '#!' + id;
});

// on load of the page: switch to the currently selected tab
var hash = window.location.hash;
// console.log(hash);
$('#myTab a[href="' + hash + '"]').tab('show');

0

Laravel çerçevesini kullanırken, benim karma sildiğinden beri bir route-> back () işlevi kullanma ile ilgili bazı sorunlar vardı. Hashimi korumak için basit bir fonksiyon oluşturdum:

$(function() {   
    if (localStorage.getItem("hash")    ){
     location.hash = localStorage.getItem("hash");
    }
}); 

ve diğer JS fonksiyonumda şu şekilde ayarladım:

localStorage.setItem("hash", myvalue);

Yerel depolama değerlerinizi istediğiniz gibi adlandırabilirsiniz; benimki hash.

Bu nedenle, karma PAGE1 üzerinde ayarlanmışsa ve PAGE2'ye giderseniz; PAGE2'de Geri'yi tıklattığınızda, karma PAGE1'de yeniden oluşturulur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.