当Firefox中的鼠标嵌入iframe时,防止父页面滚动

时间:2015-08-23 09:42:12

标签: javascript firefox iframe javascript-events mousewheel

...不限制iframe内的滚动或需要专门命名/标记所有可滚动元素。

想象一下嵌入在父页面中的谷歌地图小部件。放大窗口小部件时,显然不希望父页面滚动。

我认为previous question的答案解决了问题:

  

在iframe内滚动时,身体对此一无所知   那里发生了什么。但是当iframe卷轴到达底部或者   顶部,它滚动到正文。

     

取消从iframe传播的事件。

但该解决方案在Firefox中不起作用,因为Firefox不会 - by design - 将iframe捕获的事件传播到父页面,但奇怪的是它会滚动父页面。见jsfiddle here

$('body').bind('mousewheel DOMMouseScroll', onWheel);

function onWheel (e){
    if (e.target === iframe)
        e.preventDefault();
    console.log(e);
}

那么,当用户在Firefox中缩放嵌入式iframe中的内容时,如何阻止页面滚动?

3 个答案:

答案 0 :(得分:11)

由于它是Firefox中的一个错误,因此解决方法是直接使用scroll事件,而不是mousewheel / DOMMouseScroll事件。

我的方式:当用户在iframe上方输入鼠标时,我将标记设置为true,当他将鼠标移开时,我将其设置回false }。

然后,当用户尝试滚动,但鼠标箭头在iframe内部时,我阻止父窗口滚动。但是,遗憾的是,您不能使用通常的e.preventDefault()方法阻止窗口滚动,因此我们仍需要另一种解决方法,强制窗口精确滚动到之前已经存在的X和Y位置。

完整代码:

(function(w) {
    var s = { insideIframe: false } 

    $(iframe).mouseenter(function() {
        s.insideIframe = true;
        s.scrollX = w.scrollX;
        s.scrollY = w.scrollY;
    }).mouseleave(function() {
        s.insideIframe = false;
    });

    $(document).scroll(function() {
        if (s.insideIframe)
            w.scrollTo(s.scrollX, s.scrollY);
    });
})(window);

我已经创建了一个立即执行的函数来阻止在全局范围内定义s变量。

小提琴工作:http://jsfiddle.net/qznujqjs/16/

修改

由于你的问题没有用jQuery标记(尽管在其中,你已经使用库展示了代码),使用vanilla JS的解决方案就像上面那样简单:

(function(w) {
    var s = { insideIframe: false } 

    iframe.addEventListener('mouseenter', function() {
        s.insideIframe = true;
        s.scrollX = w.scrollX;
        s.scrollY = w.scrollY;
    });

    iframe.addEventListener('mouseleave', function() {
        s.insideIframe = false;
    });

    document.addEventListener('scroll', function() {
        if (s.insideIframe)
            w.scrollTo(s.scrollX, s.scrollY);
    });
})(window);

答案 1 :(得分:1)

鉴于所有先决条件,我认为以下是在Firefox中实现此功能的最佳方式。

iframe包裹div稍微短一些,以便在其中启用垂直滚动:

<div id="wrapper" style="height:190px; width:200px; overflow-y: auto; overflow-x: hidden;">
  <iframe id="iframeid" height="200px" width="200px" src="about:blank">
  </iframe>
</div>

现在,您可以垂直居中iframe并每次重新定位 包装器收到scroll事件(当用户试图滚动框架边缘时会发生这种情况):

var topOffset = 3;

wrapper.scrollTop(topOffset);

wrapper.on("scroll", function(e) {
    wrapper.scrollTop(topOffset);
});

将此与之前针对Chrome的修补程序相结合,它应涵盖所有主流浏览器。这是一个有效的例子 - http://jsfiddle.net/o2tk05ab/5/

唯一突出的问题是包装器div上的可见垂直滚动条。有几种方法可以解决,例如 - Hide scroll bar, but still being able to scroll

答案 2 :(得分:0)

我认为这将解决您的问题 它解决了我的问题

    var myElem=function(event){
  return $(event.toElement).closest('.slimScrollDiv')
}

$(document).mouseover(function(e){
     window.isOnSub=myElem(e).length>0



})

$(document).on('mousewheel',function(e){
  if(window.isOnSub){  
console.log(e.originalEvent.wheelDelta);      
    if( myElem(e).prop('scrollHeight')-myElem(e).scrollTop()<=myElem(e).height()&&(e.originalEvent.wheelDelta<0)){

      e.preventDefault()
    } 


}

})

将'.slimScrollDiv'替换为您想要的元素选择器 在鼠标悬停时阻止父滚动

http://jsbin.com/cutube/1/edit?html,js,output