web-dev-qa-db-fra.com

Comment désactiver l'ancre "jump" lors du chargement d'une page?

Je pense que cela n’est peut-être pas possible, je vais essayer d’expliquer du mieux que je peux .

J'utilise ce code, tel que fourni par un autre utilisateur d'une question précédente.

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

ce code fonctionne très bien lorsque je visite directement la page "Onglets".

cependant, je dois créer un lien vers des onglets individuels à partir d'autres pages. Pour ce faire, le code obtient le window.location.hash, puis l'onglet approprié.

la page ne "saute" pas à l'ancre à cause de "return false".

cet événement n'est toutefois déclenché que sur un événement de clic. Par conséquent, si je visite mes "onglets" de n'importe quelle autre page, l'effet "saut" est déclenché. Pour lutter contre cela, je fais automatiquement défiler vers le haut de la page, mais je préférerais que cela ne se produise pas.

existe-t-il un moyen de simuler un "retourne faux" lors du chargement de la page, empêchant ainsi le "saut" d'ancre.

j'espère que c'est assez clair.

merci

91
Ross

Votre solution ne fonctionne pas? Je ne suis pas sûr de bien comprendre la question. Avez-vous une page de démonstration? Tu pourrais essayer:

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

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

Edit: testé et fonctionne sous Firefox, IE et Chrome sous Windows.
Édition 2: déplacez setTimeout() dans le bloc if, props @vsync.

132
dave1010

Voir ma réponse ici: Stackoverflow Answer

L'astuce consiste simplement à supprimer le hashtag dès que possible et à stocker sa valeur pour votre propre usage:

Il est important que vous ne mettiez pas cette partie du code dans les fonctions $ () ou $ (window) .load () comme ce serait trop tard et que le navigateur est déjà passé à la balise.

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

J'ai utilisé la solution de dave1010, mais c'était un peu sidérant de la mettre dans la fonction $ (). J'ai donc fait ceci: (pas dans le $ (). Ready)

    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);
    }
11
lopsided

Il existe d’autres moyens de suivre l’onglet sur lequel vous vous trouvez. peut-être définir un cookie ou une valeur dans un champ caché, etc.

Je dirais que si vous ne voulez pas que la page saute à la charge, vous feriez mieux d'utiliser l'une de ces autres options plutôt que le hachage, car la raison principale d'utiliser le hachage de préférence est d'autoriser exactement ce que vous voulez. 'veulent bloquer.

Autre point - la page ne sautera pas si vos liens de hachage ne correspondent pas aux noms des balises dans le document. Par conséquent, si vous souhaitez continuer à utiliser le hachage, vous pouvez manipuler le contenu de sorte que les balises portent un nom différent. Si vous utilisez un préfixe cohérent, vous pourrez toujours utiliser Javascript pour naviguer entre les deux.

J'espère que cela pourra aider.

11
Spudley
  1. Le navigateur passe à <element id="abc" /> s'il existe http://site.com/#abc hash dans l'adresse et si l'élément avec id = "abc" est visible. Donc, vous devriez masquer l'élément par défaut: <element id="anchor" style="display: none" />. S'il n'y a pas d'élément visible avec id = hash sur la page, le navigateur ne sautera pas.

  2. Créez un script qui vérifie le hachage dans l'URL, puis trouve et affiche l'élément approprié (qui est masqué par défaut).

  3. Désactivez le comportement par défaut du "lien de type hachage" en liant un événement onclick à un lien et en spécifiant return false; à la suite de l'événement onclick.

Quand j'ai implémenté des onglets, j'ai écrit quelque chose comme ça:

    <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>
9
Sergei Smirnov

les CSS sales ne corrigent que de rester défilés à chaque utilisation de l'ancre (inutile si vous souhaitez toujours utiliser des ancres pour les sauts de défilement, très utile pour les liens profonds)

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

Aucune des réponses ne fonctionne assez bien pour moi, je vois que la page saute à l'ancre et ensuite au sommet pour certaines solutions, certaines réponses ne fonctionnent pas du tout, les choses peuvent changer des années J'espère que ma fonction aidera quelqu'un.

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

Bien que la réponse acceptée fonctionne bien, j’ai parfois constaté que la barre de défilement sautait énormément, en particulier sur les pages contenant de grandes images.

 window.scrollTo(0, 0);

Ce qui peut être assez gênant pour l'utilisateur.

La solution que j'ai finalement choisie est en fait assez simple: utiliser un identifiant différent sur la cible par rapport à celui utilisé dans location.hash

Par exemple:

Voici le lien sur une autre page

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

Donc bien sûr, s'il y a un élément avec un ID de tab2 sur la page des onglets, la fenêtre y passera au chargement.

Donc, vous pouvez ajouter quelque chose à l'ID pour l'empêcher:

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

Et puis vous pouvez ajouter "-noScroll" à location.hash dans le 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>
2
andrew

Dans mon cas, en raison de l'utilisation du lien d'ancrage pour le popup CSS, j'ai utilisé de cette façon:

Il suffit de sauvegarder la pageYOffset la première fois au clic, puis de définir le ScrollTop sur cette position:

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

Je pense que j'ai trouvé un moyen pour les onglets de l'interface utilisateur sans refaire la fonctionnalité. Jusqu'à présent, je n'ai trouvé aucun problème.

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

Tous dans un événement prêt. Il est précédé de "tab_" pour le hachage, mais fonctionne à la fois lorsque vous cliquez dessus et que la page contient du hachage.

1
JRomero

Une autre approche

Essayez de vérifier si la page a fait défiler et alors seulement réinitialiser la position:

var scrolled = false;

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

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

Heres a demo

0
hitautodestruct

Je n'ai pas eu de succès constant avec ces solutions.

Apparemment parce que le saut a lieu avant Javascript => Référence ( http://forum.jquery.com/topic/preventing-anchor-jump )

Ma solution est de positionner toutes les ancres au sommet par défaut avec CSS.

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

Ensuite, utilisez jquery pour faire défiler jusqu'au parent de l'ancre cible ou à un frère (éventuellement une balise em vide).

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

exemple de requête pour le défilement lorsque l'URL est entrée avec hash
(la page ne doit pas déjà être chargée dans window/tab, cela couvre les liens provenant de sources autres/extérieures)

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

Vous voudrez également empêcher les clics d'ancrage par défaut lorsque vous êtes sur la page, puis faites défiler jusqu'à leurs cibles.

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

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

La bonne chose à propos de cette méthode est que les cibles de balises d'ancrage restent structurellement à côté du contenu pertinent, bien que leur position CSS soit au sommet.

Cela devrait signifier que les robots des moteurs de recherche n'auront pas de problème.

Salut, j'espère que cela aide
Gris 

0
grayskale.com

Cela fonctionnera avec bootstrap v3 

$(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
Lasithds

Je n’ai pas eu beaucoup de succès avec les méthodes setTimeout ci-dessus dans Firefox.

Au lieu d'un setTimeout, j'ai utilisé une fonction onload:

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

C'est toujours très glitch, malheureusement.

0
bozdoz

Résolu mon problème en faisant ceci:

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

Essayez ceci pour empêcher le client de tout type de défilement vertical sur hashchanged (dans votre gestionnaire d’événements):

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

(rafraîchissement du navigateur)

0
andy