Как отключить якорь "прыжок" при загрузке страницы?


Я думаю, что это может быть невозможно, постараюсь объяснить как можно лучше. У меня есть страница, содержащая вкладки (jQuery powered), управляемые следующим образом:

Я использую этот код, как указано другим пользователем из предыдущего вопроса.

<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>

этот код отлично работает, когда я посещаю страницу "вкладки" напрямую.

однако мне нужно связать с отдельными вкладками с других страниц - поэтому для этого код получает window.location.hash затем показывает соответствующий табуляция.

страница не" прыгает "на якорь из-за"return false".

это событие запускается только на событие щелчка, однако. следовательно, если я посещаю свои "вкладки" с любой другой страницы, срабатывает эффект "прыжок". Для борьбы с этим я автоматически прокручиваю до верхней части страницы, но я бы предпочел, чтобы этого не произошло.

есть ли способ имитировать "возврат false" при загрузке страницы, предотвращая якорный "прыжок" от возникновения.

надеюсь, что это достаточно ясно.

спасибо

14 88

14 ответов:

ваше исправление не работает? Я не уверен, что правильно понял вопрос - у вас есть демо-страница? Вы можете попробовать:

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

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

Edit: протестировано и работает в Firefox, IE и Chrome на Windows.
Правка 2: перемещение setTimeout() внутри if блок, реквизит @vsync.

смотрите мой ответ здесь: Stackoverflow Ответ

хитрость заключается в том, чтобы просто удалить хэштег как можно скорее и сохранить его значение для вашего собственного использования:

важно, чтобы вы не помещали эту часть кода в окно $() или $().load () функции, как это было бы поздно, и браузер уже перешел к тегу.

// 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 () {});
    }
});

есть и другие способы отслеживания того, на какой вкладке вы находитесь; возможно, установка файла cookie или значения в скрытом поле и т. д. и т. д.

Я бы сказал, что если вы не хотите, чтобы страница прыгала при загрузке, вам было бы лучше использовать один из этих других вариантов, а не хэш, потому что основная причина использования хэша в предпочтении к ним-разрешить именно то, что вы хотите заблокировать.

еще один момент - страница не будет прыгать, если ваш хэш-ссылки не совпадают с именами теги в документе, поэтому, возможно, если вы хотите продолжать использовать хэш, вы можете манипулировать содержимым, чтобы теги назывались по-разному. Если вы используете последовательный префикс, вы все равно сможете использовать Javascript для перехода между ними.

надеюсь, что это поможет.

я использовал решение dave1010, но это было немного нервным, когда я положил его в $().готовая функция. Поэтому я сделал это: (не внутри $().готов)

    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);
    }
  1. браузер переходит к <element id="abc" /> если есть http://site.com/#abc хэш в поле адреса и элемент с ID="ABC" является видимым. Итак, вы просто должны скрыть элемент по умолчанию:<element id="anchor" style="display: none" />. Если на странице нет видимого элемента с id=hash, браузер не будет прыгать.

  2. создайте скрипт, который проверяет хэш в url, а затем находит и показывает элемент prrpopriate (который скрыт неисполнение.)

  3. отключите поведение "хэш-подобной ссылки" по умолчанию, привязав событие onclick к ссылке и указав return false; в результате события onclick.

когда я реализовал вкладки, я написал что-то вроде этого:

    <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>

грязный CSS только исправить, чтобы оставаться прокручивается каждый раз, когда якорь используется (не полезно, если вы все еще хотите использовать якоря для прокрутки прыжков, очень полезно для deeplinking):

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

ни один из ответов не работает достаточно хорошо для меня, я вижу, что страница прыгает на якорь, а затем на вершину для некоторых решений, некоторые ответы вообще не работают, могут быть вещи изменены в течение многих лет. Надеюсь, моя функция поможет кому-то.

/**
 * 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
        );
    });
}

хотя принятый ответ работает хорошо, я обнаружил, что иногда, особенно на страницах, содержащих большие изображения, полоса прокрутки будет прыгать дико, используя

 window.scrollTo(0, 0);

который может быть довольно отвлекающим для пользователя.

решение, на котором я остановился в конце концов, на самом деле довольно простое, и это использовать другой идентификатор на цели к тому, который используется в location.hash

например:

вот ссылка на некоторые другие страница

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

так что, конечно, если есть элемент с идентификатором tab2 на странице вкладки окно перейдет к нему при загрузке.

так что вы можете добавить что-то к ID, чтобы предотвратить это:

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

и тогда вы можете добавить "-noScroll" до location.hash в javascript:

<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>

Я думаю, что нашел способ для вкладок пользовательского интерфейса без повторного использования функциональности. До сих пор я не нашел никаких проблем.

    $( ".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);

все внутри события ready. Он добавляет "tab_" для хэша, но работает как при нажатии, так и при загрузке страницы с хэшем.

другой подход

попробуйте проверить, если страница была прокручена и только потом сбросить установки:

var scrolled = false;

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

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

вот демо

Я не имел большого успеха с выше setTimeout методы в Firefox.

вместо setTimeout, я использовал функцию onload:

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

это все еще очень Глюк, к сожалению.

у меня не было никакого последовательного успеха с этими решениями.

видимо из-за того, что скачок происходит до Javascript => ссылка(http://forum.jquery.com/topic/preventing-anchor-jump)

мое решение состоит в том, чтобы расположить все якоря в верхней части по умолчанию с помощью CSS.

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

затем используйте jquery для прокрутки до родителя целевого якоря или брата(возможно, пустой тег em)

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

пример jQuery для прокрутка для того, когда URL вводится с хэшем
(страница не должна быть уже загружена в разделе окна, это касается одной из других внешних источников)

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);

кроме того, вы хотите, чтобы предотвратить по умолчанию для якорных кликов в то время как на странице, а затем прокрутите до своих целей

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

и 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;
});

хорошая вещь об этом методе-это цели тега привязки, остающиеся структурно рядом с соответствующим контентом, хотя их позиция CSS находится на верхний.

Это должно означать, что поисковые роботы не будут иметь проблемы.

Ура, я надеюсь, что это поможет
серый

попробуйте это, чтобы предотвратить клиента от любого вида вертикальной прокрутки на hashchanged (внутри обработчика событий):

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

(браузер перерисовывать)

решил мой промлем, сделав это:

// 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);
});`