防止滚动从元素冒泡到窗口

时间:2009-09-22 12:04:39

标签: javascript jquery html events scroll

我有一个包含iframe的模态框窗口(弹出窗口),
 在 iframe 里面有一个可滚动的 div

当我滚动iframe的内部DIV并且它已达到其上限或下限时,浏览器本身的窗口开始滚动。这是不受欢迎的行为

我尝试了类似这样的东西,当鼠标进入弹出框区域时,当onMouseEnter时会杀死主窗口滚动:

e.preventDefault()因某种原因无法正常工作......

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

更新

似乎现在在2013年e.preventDefault();就够了......

15 个答案:

答案 0 :(得分:26)

很抱歉,据我所知,无法取消任何类型的滚动事件。

W3MSDN都说:

Cancelable  No
Bubbles     No

我认为你不得不把它留给浏览器作者修复。 Firefox(无论如何,在Linux上为3.5)对我来说似乎有一个更好的行为:如果孩子在你开始时使用滚轮已经位于顶端/底端,它只会滚动父对象。< / p>

答案 1 :(得分:17)

如果我们无法阻止窗口滚动,为什么不撤消它呢? 也就是说,捕捉滚动事件然后滚动回固定位置。

以下代码锁定Y轴,只要一个悬停在$("#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;
});

我将此用于http://bundestube.de/上的查询建议框(在顶部搜索框中输入一些字符以使可滚动窗格可见):

Screenshot

这在Chrome / Safari(Webkit)中完美运行,并且在Firefox和Opera中存在一些滚动故障。出于某种原因,它不适用于我的IE安装。我想这与jQuery的悬停方法有关,这种方法似乎在100%的情况下无法正常工作。

答案 2 :(得分:4)

使用简单的CSS属性(对于现代浏览器)已解决:
overscroll-behavior

body{
  height: 600px;
  overflow: auto;
}

section{
  width: 50%;
  height: 50%;
  overflow: auto;
  background: lightblue;
  overscroll-behavior: none; /*   <--- the trick    */
}

section::before{
  content: '';
  height: 200%;
  display: block;
}
<section>
 <input value='end' />
</section>

只需将该样式属性应用于应该将滚动“锁定”到的元素上,滚动事件就不会冒泡到可能也具有滚动的任何父元素。


与上面相同的演示,但没有诀窍:

body{
  height: 600px;
  overflow: auto;
}

section{
  width: 50%;
  height: 50%;
  overflow: auto;
  background: lightblue;
}

section::before{
  content: '';
  height: 200%;
  display: block;
}
<section>
 <input value='end' />
</section>

答案 3 :(得分:3)

我知道这是一个相当古老的问题,但由于这是google中的最佳结果之一...我不得不以某种方式取消滚动冒泡而不使用jQuery,这段代码对我有用:

function preventDefault(e) {
  e = e || window.event;
  if (e.preventDefault)
    e.preventDefault();
  e.returnValue = false;  
}

document.getElementById('a').onmousewheel = function(e) { 
  document.getElementById('a').scrollTop -= e. wheelDeltaY; 
  preventDefault(e);
}

答案 4 :(得分:3)

我的jQuery插件:

$('.child').dontScrollParent();

$.fn.dontScrollParent = function()
{
    this.bind('mousewheel 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).height())
            return false;

        return true;
    });
}

答案 5 :(得分:1)

我是如何解决问题的:

打开弹出窗口时,我会调用以下内容:

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

然后,当我关闭弹出窗口时,我称之为:

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

弹出窗口是模态的,因此不需要与底层主体进行交互

效果很好

答案 6 :(得分:0)

显然,您可以设置overflow:hidden to prevent scrolling。如果文档已经滚动,不知道怎么回事。我也是一台没有鼠标的笔记本电脑,所以今晚我没有滚轮测试:-)这可能值得一试。

答案 7 :(得分:0)

您可以在iframe中尝试jscroll窗格来替换默认滚动。

http://www.kelvinluck.com/assets/jquery/jScrollPane/jScrollPane.html

我不确定,但试一试

答案 8 :(得分:0)

这就是我的所作所为:

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

demo fiddle

使用CSS overflow:hidden隐藏滚动条,因为如果它们拖动它将无效。

跨浏览器工作

答案 9 :(得分:0)

这里有新的网络开发者。在IE和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();
        }
    }
}

不要让行数欺骗你,这很简单 - 只是有点冗长的可读性(自我记录代码ftw对吗?)

答案 10 :(得分:0)

我想添加一些我认为效果最好的更新代码:

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

上面已经提到过的这一点和一点之间的区别是添加了更多事件以及使用 outerHeight()而不是 height()来避免崩溃如果元素有填充!

答案 11 :(得分:0)

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

答案 12 :(得分:0)

截至目前的2018年,e.preventDefault就足够了。

green

这会阻止滚动到父级。

答案 13 :(得分:0)

尝试以下代码:

var container = document.getElementById('a');
container.onwheel = (e) => {
    const deltaY = e.wheelDeltaY || -(e.deltaY * 25); // Firefox fix
    container.scrollTop -= deltaY;
    e.preventDefault();
    e.stopPropagation();
    e.returnValue = false;
};

答案 14 :(得分:-2)

function stopPropogation(e)
{
    e = e || window.event;
    e.cancelBubble = true;
    if (e.stopPropagation) e.stopPropagation();
    if (e.preventDefault) e.preventDefault();
}

这应该有用。