Bir sayfa yüklerken bağlantı "atlama" nasıl devre dışı bırakılır?


111

Bunun mümkün olmayabileceğini düşünüyorum, elimden geldiğince iyi açıklamaya çalışacağım. Aşağıdakiler tarafından kontrol edilen sekmeler içeren (jquery destekli) bir sayfam var:

Önceki sorudan başka bir kullanıcı tarafından sağlanan bu kodu kullanıyorum.

<script type="text/javascript">
    $(function() {

     $('html, body').animate({scrollTop:0}); // this is my "fix"

        var tabContent = $(".tab_content");
        var tabs = $("#menu li");
        var hash = window.location.hash;
     tabContent.not(hash).hide();
        if(hash=="") {
      $('#tab1').fadeIn();
     }
        tabs.find('[href=' + hash + ']').parent().addClass('active');

        tabs.click(function() {
            $(this).addClass('active').siblings().removeClass('active');
            tabContent.hide();
            var activeTab = $(this).find("a").attr("href");

            $(activeTab).fadeIn();
           return false;
        });

    });
</script>

doğrudan "sekmeler" sayfasını ziyaret ettiğimde bu kod harika çalışıyor.

ancak, diğer sayfalardan tek tek sekmelere bağlantı vermem gerekiyor - bunu yapmak için, kod daha window.location.hashsonra uygun sekmeyi gösterir.

sayfa "yanlış dönüş" nedeniyle bağlantıya "atlamaz".

ancak bu olay yalnızca bir tıklama olayında tetiklenir. dolayısıyla, başka bir sayfadan "sekmelerimi" ziyaret edersem, "atlama" efekti tetiklenir. Bununla mücadele etmek için otomatik olarak sayfanın üst kısmına gidiyorum, ancak bunun olmamasını tercih ederim.

sayfa yüklendiğinde "yanlış döndürme" simülasyonunun bir yolu var mı, bağlantı "atlamasının" oluşmasını engelliyor.

Umarım bu yeterince açıktır.

Teşekkürler

Yanıtlar:


143

Düzeltmeniz çalışmıyor mu? Soruyu doğru anladığımdan emin değilim - bir demo sayfanız var mı? Deneyebilirsin:

if (location.hash) {
  setTimeout(function() {

    window.scrollTo(0, 0);
  }, 1);
}

Düzenleme: Windows'ta Firefox, IE ve Chrome'da test edildi ve çalışıyor.
Düzenleme 2: bloğun setTimeout()içinde hareket edin if, @vsync sahne.


2
kahraman! Evet, "düzeltmem" işe yaradı, ancak sayfa "kaydırılır" (kodumun söylediği gibi) ve kaymamasını tercih ederim. kodunuz mükemmel çalışıyor. ScrollTo'ya bakmadım - işlev gerekli mi? sadece window.scrollTo (0, 0) ile sorunsuz çalışıyor gibi görünüyor;
Ross

3
Firefox'ta boş bir sayfada denedim setTimeoutve her zaman işe yaramadı. $(function() {Yine de jQuery'nin içindeyse muhtemelen buna ihtiyacınız yoktur . Buna gerçekten ihtiyacınız yok location.hash, ancak tarayıcıların hiçbir şey yapmasına gerek kalmaması için onu açık bırakmak güzel. Ayrıca scrollTo'nun ne için olduğunu size hatırlatır!
dave1010

2
Bugün aynı sorunu yaşadım. Aslında karma (sekme adları / href değerleri ile aynı) nav bağlantılarıma eklemek zorunda kaldım. Sonunda sekmelerime 1 karakterlik bir son ek ekledim ve ardından değerleri window.location.hash ile karşılaştırırken değerleri 1 karakter (str.slice (0, -1) ile alt sıraya dizdim Bu şekilde karmalar farklıdır ve atlama olmaz .
geliştirici10

1
ifİçeride değil, dışarıda olmalı. ayrıca, aralık için minimum yaklaşık 10'dur, bu nedenle 0 veya 1 aynıdır ... tarayıcıya bağlı olarak 10.
vsync

2
Bu, tarayıcının hashtag'e atlamasını ENGELLEMEZ, 'sıçramayı' önlemek için boş bir hashtag koymalısınız, cevabıma buradan bakın stackoverflow.com/a/29823913/826194
Larzan

43

Cevabımı burada görün: Stackoverflow Cevap

İşin püf noktası, hashtag'i en kısa sürede kaldırmak ve değerini kendi kullanımınız için saklamaktır:

Kodun o kısmını $ () veya $ (window) .load () işlevlerine koymamanız önemlidir, çünkü çok geç olacaktır ve tarayıcı zaten etikete taşınmıştır.

// store the hash (DON'T put this code inside the $() function, it has to be executed 
// right away before the browser can start scrolling!
var target = window.location.hash,
    target = target.replace('#', '');

// delete hash so the page won't scroll to it
window.location.hash = "";

// now whenever you are ready do whatever you want
// (in this case I use jQuery to scroll to the tag after the page has loaded)
$(window).on('load', function() {
    if (target) {
        $('html, body').animate({
            scrollTop: $("#" + target).offset().top
        }, 700, 'swing', function () {});
    }
});

1
FF ile gerçekten uzun bir listeye sahip bir div üzerinde max-height overflow-y kullandığım bir hatayla karşılaştım, FF gizli düğümün dom içinde olacağı yerde aşağı kaydırırdı. Bu yalnızca gerçek kodun ilk üç satırını kullandı (yorumları değil) ve bu, FireFox ile ilgili sorunumu düzeltti.
JQII

12

Hangi sekmede olduğunuzu izlemenin başka yolları da vardır; belki bir çerez veya gizli bir alanda bir değer vb. ayarlamak.

Sayfanın yüklenirken atlamasını istemiyorsanız, hash yerine bu diğer seçeneklerden birini kullanmanızın daha iyi olacağını söyleyebilirim, çünkü hash'i tercih etmede kullanmanın ana nedeni, tam olarak size izin vermektir. engellemek istiyoruz.

Başka bir nokta - hash bağlarınız belgedeki etiketlerin adlarıyla eşleşmiyorsa sayfa atlamaz, bu nedenle belki de hash'i kullanmaya devam etmek istiyorsanız, etiketleri farklı bir şekilde adlandırılacak şekilde içeriği değiştirebilirsiniz. Tutarlı bir önek kullanırsanız, o zaman arasında geçiş yapmak için Javascript'i kullanmaya devam edebilirsiniz.

Umarım yardımcı olur.


2
Güzel nokta. Sayfayı JS / CSS kapalıyken kullanılabilir / erişilebilir tutmayı unutmayın.
dave1010

12

Dave1010'un çözümünü kullandım, ancak $ (). Ready işlevinin içine koyduğumda biraz ürktü. Ben de bunu yaptım: ($ () içinde değil. Hazır)

    if (location.hash) {               // do the test straight away
        window.scrollTo(0, 0);         // execute it straight away
        setTimeout(function() {
            window.scrollTo(0, 0);     // run it a bit later also for browser compatibility
        }, 1);
    }

10
  1. Tarayıcı , adreste http://site.com/#abc karma değeri <element id="abc" />varsa ve id = "abc" olan öğe görünürse konumuna atlar . Yani, sadece varsayılan olarak eleman gizlemek olmalıdır: . Sayfada id = hash olan görünür bir öğe yoksa, tarayıcı atlamaz.<element id="anchor" style="display: none" />

  2. Url'deki karmayı kontrol eden ve ardından prrpopriate öğesini bulup gösteren (varsayılan olarak gizlidir) bir komut dosyası oluşturun.

  3. Bir onclick olayını bir bağlantıya bağlayarak varsayılan "karma benzeri bağlantı" davranışını devre dışı bırakın ve return false;onclick olayının sonucu olarak belirtin .

Sekmeleri uyguladığımda şöyle bir şey yazdım:

    <script>
    $(function () {         
        if (location.hash != "") {
            selectPersonalTab(location.hash);
        }
        else {
            selectPersonalTab("#cards");
        }
    });

    function selectPersonalTab(hash) {
        $("#personal li").removeClass("active");
        $("a[href$=" + hash + "]").closest("li").addClass("active");
        $("#personaldata > div").hide();
        location.hash = hash;
        $(hash).show();
    }

    $("#personal li a").click(function (e) {
        var t = e.target;
        if (t.href.indexOf("#") != -1) {
            var hash = t.href.substr(t.href.indexOf("#"));
            selectPersonalTab(hash);
            return false;
        }
    });
</script>

6

Cevapların hiçbiri benim için yeterince iyi çalışmıyor, bazı çözümler için sayfanın çapa atladığını ve sonra zirveye çıktığını görüyorum, bazı cevaplar hiç işe yaramıyor, yıllarca değişen şeyler olabilir. Umarım işlevim birine yardımcı olur.

/**
 * Prevent automatic scrolling of page to anchor by browser after loading of page.
 * Do not call this function in $(...) or $(window).on('load', ...),
 * it should be called earlier, as soon as possible.
 */
function preventAnchorScroll() {
    var scrollToTop = function () {
        $(window).scrollTop(0);
    };
    if (window.location.hash) {
        // handler is executed at most once
        $(window).one('scroll', scrollToTop);
    }

    // make sure to release scroll 1 second after document readiness
    // to avoid negative UX
    $(function () {
        setTimeout(
            function () {
                $(window).off('scroll', scrollToTop);
            },
            1000
        );
    });
}

Şimdiye kadar bulduğum en iyi çözüm. Ve aslında çok şey gördüm.
MarkSkayff

Bunun için teşekkür ederim! Ayrıca saatler süren denemelerden sonra benim için işe yarayan tek çözüm, ancak bu çözümün benim için en iyi yanı, karmayı kaldırmam gerekmemesi.
Chris Vecchio

Bu, kaydırıcı sayfa yüklenirken sayfanın üst kısmındaysa çalışmaz, ardından her zamanki gibi aşağı kaydırılır ve sayfa tamamlandıktan sonra en üste atlar. Durumun böyle olduğunu bilen var mı?
robgha01

@ robgha01 lütfen işlevin mümkün olan en kısa sürede çalıştırıldığından ve herhangi bir olayı beklemediğinden emin olun, bu yanlış: $(document).ready(function () { preventAnchorScroll(); });JavaScript'inizin en başında işlevi çağırmanız yeterlidir . Şimdi test ettim, Chrome, Firefox ve Opera'da benim için çalışıyor.
kdmitry

4

kirli CSS yalnızca, çapa her kullanıldığında yukarı kaydırılmış olarak kalacak şekilde düzeltildi (yine de kaydırma atlamaları için çapa kullanmak istiyorsanız kullanışlı değildir, derin bağlantı için çok yararlıdır):

.elementsWithAnchorIds::before {
   content: "";
   display: block;
   height: 9999px;
   margin-top: -9999px; //higher thin page height
}

soooooo akıllı!
duhaime

3

Kabul edilen cevap iyi çalışsa da, bazen, özellikle büyük resimler içeren sayfalarda kaydırma çubuğunun çılgınca atlayacağını fark ettim.

 window.scrollTo(0, 0);

Bu, kullanıcı için oldukça rahatsız edici olabilir.

Sonunda kararlaştırdığım çözüm aslında oldukça basit ve bu, hedefte kullanılandan farklı bir kimlik kullanmaktır. location.hash

Örneğin:

İşte başka bir sayfadaki bağlantı

<a href="/page/with/tabs#tab2">Some info found in tab2 on tabs page</a>

Tabi ki tab2sekmeler sayfasında kimliği olan bir öğe varsa , pencere yüklenirken ona atlayacaktır.

Yani bunu önlemek için kimliğe bir şey ekleyebilirsiniz:

<div id="tab2-noScroll">tab2 content</div>

Sonra da ekleyebilirsiniz "-noScroll"için location.hashjavascript:

<script type="text/javascript">
    $(function() {

        var tabContent = $(".tab_content");
        var tabs = $("#menu li");
        var hash = window.location.hash;


     tabContent.not(hash + '-noScroll').hide();                           
        if(hash=="") {       //^ here
      $('#tab1-noScroll').fadeIn();
     }
        tabs.find('[href=' + hash + ']').parent().addClass('active');

        tabs.click(function() {
            $(this).addClass('active').siblings().removeClass('active');
            tabContent.hide();
            var activeTab = $(this).find("a").attr("href") + '-noScroll'; 
                                                               //^ and here

            $(activeTab).fadeIn();
           return false;
        });

    });
</script>

2

Benim durumumda, CSS açılır penceresi için çapa bağlantısı kullandığım için şu şekilde kullandım:

İlk olarak tıklamayla sayfayı ayarlayın ve ardından ScrollTop öğesini buna ayarlayın:

$(document).on('click','yourtarget',function(){
        var st=window.pageYOffset;
        $('html, body').animate({
                'scrollTop' : st
            });
});

Diğer çözümleri denedikten sonra, benim için işe yarayan buydu, benim durumumda birlikte çalıştığım web sitesi, bir ödemenin belirli bir bölümünü yüklemek için url'de # kullandı. URL'deki hash için ödeme işlevini değiştirmek yerine bunu kullandım. Teşekkürler
chris c

1

Sanırım, işlevselliği yeniden yapmadan UI Sekmeleri için bir yol buldum. Şimdiye kadar herhangi bir sorun bulamadım.

    $( ".tabs" ).tabs();
    $( ".tabs" ).not(".noHash").bind("tabsshow", function(event, ui) { 
        window.location.hash = "tab_"+ui.tab.hash.replace(/#/,"");
        return false;
    });

    var selectedTabHash = window.location.hash.replace(/tab_/,"");
    var index = $( ".tabs li a" ).index($(".tabs li a[href='"+selectedTabHash+"']"));
    $( ".tabs" ).not(".noHash").tabs('select', index);

Hepsi hazır bir olay içinde. Karmanın başına "tab_" ekler ancak hem tıklandığında hem de karma ile yüklendiğinde çalışır.


1

Bu, bootstrap v3 ile çalışacak

$(document).ready(function() {
  if ($('.nav-tabs').length) {
    var hash = window.location.hash;
    var hashEl = $('ul.nav a[href="' + hash + '"]');
    hash && hashEl.tab('show');

    $('.nav-tabs a').click(function(e) {
      e.preventDefault();
      $(this).tab('show');
      window.location.hash = this.hash;
    });

    // Change tab on hashchange
    window.addEventListener('hashchange', function() {
      var changedHash = window.location.hash;
      changedHash && $('ul.nav a[href="' + changedHash + '"]').tab('show');
    }, false);
  }
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<div class="container">
<ul class="nav nav-tabs">
  <li class="active"><a data-toggle="tab" href="#home">Home</a></li>
  <li><a data-toggle="tab" href="#menu1">Menu 1</a></li>
</ul>

<div class="tab-content">
  <div id="home" class="tab-pane fade in active">
    <h3>HOME</h3>
    <p>Some content.</p>
  </div>
  <div id="menu1" class="tab-pane fade">
    <h3>Menu 1</h3>
    <p>Some content in menu 1.</p>
  </div>
</div>
</div>


0

Başka bir yaklaşım

Sayfanın kaydırılıp kaydırılmadığını kontrol etmeyi ve yalnızca o zaman konumu sıfırlamayı deneyin:

var scrolled = false;

$(window).scroll(function(){
  scrolled = true;
});

if ( window.location.hash && scrolled ) {
  $(window).scrollTop( 0 );
}

Heres a demo


çalışmıyor kardeşim ... ilk yük altta ... yenilemeden sonra üstte kalıyor
Martin Zvarík

0

setTimeoutFirefox'ta yukarıdaki yöntemlerle pek başarılı olamadım.

SetTimeout yerine bir onload işlevi kullandım:

window.onload = function () {
    if (location.hash) {
        window.scrollTo(0, 0);
    }
};

Maalesef hala çok sorunlu.


çünkü onload, fotoğraflar da dahil olmak üzere her şey tamamen yüklendikten sonra çalışır ... bu yüzden tabii ki bu şekilde aksaklık olur
Martin Zvarík

0

Bu çözümlerle tutarlı bir başarı elde etmedim.

Görünüşe göre, atlamanın Javascript => referanstan önce gerçekleşmesi nedeniyle ( http://forum.jquery.com/topic/preventing-anchor-jump )

Çözümüm, tüm bağlantıları varsayılan olarak CSS ile en üstte konumlandırmaktır.

.scroll-target{position:fixed;top:0;left:0;}

Ardından, hedef tutturucunun veya bir kardeşin (boş bir em etiketi) üst öğesine gitmek için jquery kullanın

<a class="scroll-target" name="section3"></a><em>&nbsp</em>

URL'nin hash ile girildiği zamanlar için kaydırma için jquery örneği
(sayfa, pencere / sekmede önceden yüklenmemelidir, bu, diğer / dış kaynaklardan gelen bağlantıları kapsar)

setTimeout(function() {
    if (window.location.hash) {               
        var hash = window.location.hash.substr(1);   
        var scrollPos = $('.scroll-target[name="'+hash+'"]').siblings('em').offset().top; 
        $("html, body").animate({ scrollTop: scrollPos }, 1000);    
    }
}, 1);

Ayrıca, sayfadayken bağlantı tıklamaları için varsayılanı önlemek ve ardından hedeflerine kaydırmak isteyeceksiniz.

<a class="scroll-to" href="#section3">section three</a>

ve jquery

$('a.scroll-to').click(function(){
    var target = $(this).attr('href').substr(1);
    var scrollPos = $('.scroll-target[name="'+target+'"]').siblings('em').offset().top; 
    $("html, body").animate({ scrollTop: scrollPos }, 1000);
    return false;
});

Bu yöntemin iyi yanı, CSS konumlarının en üstte olmasına rağmen, bağlantı etiketi hedeflerinin yapısal olarak ilgili içeriğin yanında kalmasıdır.

Bu, arama motoru tarayıcılarının bir sorunu olmayacağı anlamına gelmelidir.

Şerefe, umarım bu
Gray'e yardımcı olur


0

İstemcinin hashchanged üzerinde herhangi bir dikey kaydırma yapmasını önlemek için bunu deneyin (olay işleyicinizin içinde):

var sct = document.body.scrollTop;
document.location.hash = '#next'; // or other manipulation
document.body.scrollTop = sct;

(tarayıcı yeniden çizilir)


0

Bunu yaparak sorunumu çözdüm:

// navbar height 
var navHeigth = $('nav.navbar').height();    

// Scroll to anchor function
var scrollToAnchor = function(hash) {
  // If got a hash
  if (hash) {
    // Scroll to the top (prevention for Chrome)
    window.scrollTo(0, 0);
    // Anchor element
    var term = $(hash);

    // If element with hash id is defined
    if (term) {

      // Get top offset, including header height
      var scrollto = term.offset().top - navHeigth;

      // Capture id value
      var id = term.attr('id');
      // Capture name value
      var name = term.attr('name');

      // Remove attributes for FF scroll prevention
      term.removeAttr('id').removeAttr('name');
      // Scroll to element
      $('html, body').animate({scrollTop:scrollto}, 0);

      // Returning id and name after .5sec for the next scroll
      setTimeout(function() {
        term.attr('id', id).attr('name', name);
      }, 500);
    }
  }
};

// if we are opening the page by url
if (location.hash) {
  scrollToAnchor(location.hash);
}

// preventing default click on links with an anchor
$('a[href*="#"]').click(function(e) {
  e.preventDefault();
  // hash value
  var hash = this.href.substr(this.href.indexOf("#"));
  scrollToAnchor(hash);
});`
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.