prevent Scroll “bubbling” from element to window

2019-01-04 09:29发布

I have a modal box window (pop-up) that contains an iframe,
and inside that iframe there's a div that is scrollable.

When I scroll the iframe's inner DIV, and it has reached its top or bottom limit,
the window of the browser itself starts to scroll. this is an unwanted behavior.

I've tried something like this, which kills the main window scroll when
onMouseEnter when mouse enters pop-up box area:

e.preventDefault() is not working as it should for some reason...

$("#popup").mouseenter(function(){
   $(window).bind("scroll", function(e){
        e.preventDefault();
   }); 
}).mouseleave(function(){
    $(window).unbind("scroll");
});

Update

Seems like now in 2013 e.preventDefault(); is enough...

13条回答
神经病院院长
2楼-- · 2019-01-04 10:09

If we cannot prevent window scrolling, why not undo it? That is, catching the scroll event and then scrolling back to a fixed position.

The following code locks the Y-Axis as long as one hovers over $("#popup"):

// here we store the window scroll position to lock; -1 means unlocked
var forceWindowScrollY = -1;

$(window).scroll(function(event) {
  if(forceWindowScrollY != -1 && window.scrollY != forceWindowScrollY) {
    $(window).scrollTop(forceWindowScrollY);    
  }
});

$("#popup").hover(function() {
  if(forceWindowScrollY == -1) {
    forceWindowScrollY = $(window).scrollTop();
  }
}, function() {
  forceWindowScrollY = -1;
});

I use this for the query suggest box on http://bundestube.de/ (enter some characters into the top search box to make the scrollable pane visible):

Screenshot

This works flawlessly in Chrome/Safari (Webkit) and with some scrolling glitches in Firefox and Opera. For some reason, it does not work with my IE installation. I guess this has to do with jQuery's hover method, which appears to not work correctly in 100% of all cases.

查看更多
走好不送
3楼-- · 2019-01-04 10:10

New web dev here. This worked like a charm for me on both IE and Chrome.

static preventScrollPropagation(e: HTMLElement) {
    e.onmousewheel = (ev) => {
        var preventScroll = false;
        var isScrollingDown = ev.wheelDelta < 0;
        if (isScrollingDown) {
            var isAtBottom = e.scrollTop + e.clientHeight == e.scrollHeight;
            if (isAtBottom) {
                preventScroll = true;
            }
        } else {
            var isAtTop = e.scrollTop == 0;
            if (isAtTop) {
                preventScroll = true;
            }
        }
        if (preventScroll) {
            ev.preventDefault();
        }
    }
}

Don't let the number of lines fool you, it is quite simple - just a bit verbose for readability (self documenting code ftw right?)

查看更多
【Aperson】
4楼-- · 2019-01-04 10:10

That's how I solved the problem:

I call the following when I open the popup:

$('body').css('overflow','hidden');

Then, when I close the popup I call this:

$('body').css('overflow','auto');

The popup is meant to be modal so no interaction is required with the underlying body

Works pretty well

查看更多
闹够了就滚
5楼-- · 2019-01-04 10:14

I would like to add a bit updated code that I found to work best:

var yourElement = $('.my-element');

yourElement.on('scroll mousewheel wheel DOMMouseScroll', function (e) {
    var delta = e.originalEvent.wheelDelta || -e.originalEvent.detail;

    if (delta > 0 && $(this).scrollTop() <= 0)
        return false;
    if (delta < 0 && $(this).scrollTop() >= this.scrollHeight - $(this).outerHeight())
        return false;

    return true;
});

The difference between this one and one that is already mentioned above is the addition of more events and the usage of outerHeight() instead of height() to avoid crashing if element has padding!

查看更多
姐就是有狂的资本
6楼-- · 2019-01-04 10:14

Here's what I do:

  $('.noscroll').on('DOMMouseScroll mousewheel', function(ev) {
     var prevent = function() {
         ev.stopPropagation();
         ev.preventDefault();
         ev.returnValue = false;
         return false;
     }
     return prevent();
  }); 

demo fiddle

Use CSS overflow:hidden to hide the scrollbar as this will do nothing if they drag it.

Works cross-browser

查看更多
冷血范
7楼-- · 2019-01-04 10:14
$('.scrollable').on('DOMMouseScroll mousewheel', function (e) {
    var up = false;
    if (e.originalEvent) {
        if (e.originalEvent.wheelDelta) up = e.originalEvent.wheelDelta / -1 < 0;
        if (e.originalEvent.deltaY) up = e.originalEvent.deltaY < 0;
        if (e.originalEvent.detail) up = e.originalEvent.detail < 0;
    }

    var prevent = function () {
        e.stopPropagation();
        e.preventDefault();
        e.returnValue = false;
        return false;
    }

    if (!up && this.scrollHeight <= $(this).innerHeight() + this.scrollTop + 1) {
        return prevent();
    } else if (up && 0 >= this.scrollTop - 1) {
        return prevent();
    }
});
查看更多
登录 后发表回答