简体   繁体   中英

Preventing scroll event when clicking an anchor bookmark

Clicking the anchor bookmark triggers a scroll event.

How to trigger the callback only when the user scroll happens and not when clicking the bookmark links?


Note: a poorly worded question with an answer was closed, but I believe it could still be useful to the community because I didn't see a similar question answered on StackOverflow

Shomz solution relies on the anchor element being in the scrolling context of the document. If the element is not in the scrolling context of the document the offset check may fail:

<body>
    <div style="max-height: 200px; overflow: auto">
    <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
    <a name="myanchor">anchor</a>
</body>

I think there are other solutions as well:

debounce

Detect when an anchor link was clicked ( hashchange / onclick ) and debounce the scroll event.

var debounce = false;
window.addEventListener("hashchange", function () { // also add one for `onclick`
    debounce = true;
    setTimeout(function () {
        debounce = false;
    }, 1);
});
window.addEventListener("scroll", function () {
    if (debounce) {
        return;
    }
    // .. handle scroll
});

onwheel

Depending on why exactly you don't want to trigger your scroll handler when you navigate to an anchor, you could consider attaching it only to the onwheel event. This means that other means of scrolling (touch, anchors, arrow keys, Page Down , etc.) wont trigger your handler.

While it's not possible to prevent the actual event from firing (because it's a part of the browser code and it works like that by design), what can be done is to extend your check conditions - in addition to $(window).scrollTop() > 0 that was originally there, you can also check whether there is a hash in the window location, and if there is, check if the scrolled amount is different from the vertical offset of the element referenced by the URL hash.

Something like this:

$(window).scroll(function(){
    if($(window).scrollTop() > 0 &&            // if it's scrolled and
       (!window.location.hash ||               // if there's no hash or
       $(window.location.hash).offset() &&     // there is, but the scroll is elsewhere
       $(window.location.hash).offset().top != $(window).scrollTop())
   ) {
        alert('scroll');                       // trigger the callback
    }
});

Live code:

 $(window).scroll(function(){ if($(window).scrollTop() > 0 && ($('#c:checked').length == 0 || (!window.location.hash || $(window.location.hash).offset() && $(window.location.hash).offset().top != $(window).scrollTop() ) ) ) { $('div').addClass('on'); setTimeout(function(){ $('div').removeClass('on'); }, 1000) } }); 
 p {margin: 500px 0;} div {position: fixed; top: 0; right: 0; opacity: 0.1; transition: all .2s linear; padding: 4px 8px} div.on {opacity: 1; background: #cfc;} 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input id="c" type="checkbox" checked="checked">Prevent scroll callback on link clicks<br> <a href="#shomz">Link to the anchor below</a> <p id="shomz">Anchor here</p> <div>Scroll triggered</div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM