Javascript 如何防止iFrame操作导致外部页面滚动到它

Javascript 如何防止iFrame操作导致外部页面滚动到它,javascript,iframe,browser,scroll,Javascript,Iframe,Browser,Scroll,首先,我知道关于这一现象有很多问题,但到目前为止给出的解决办法中没有一个对我现在的情况有所帮助 环境: 我的代码在我无法控制的页面的外部iFrame中。它的大小适合我的所有内容,因此在我的iFrame中不会发生滚动。相反,外部页面可以上下滚动以查看其内容 问题: 我有一个内部iFrame,里面有我无法控制的第三方广告。如果内部iFrame运行以下任何Javascript命令,则外部页面向下滚动所有内容以查看内部iFrame: 模糊并聚焦其中的元素 window.location.href或do

首先,我知道关于这一现象有很多问题,但到目前为止给出的解决办法中没有一个对我现在的情况有所帮助

环境: 我的代码在我无法控制的页面的外部iFrame中。它的大小适合我的所有内容,因此在我的iFrame中不会发生滚动。相反,外部页面可以上下滚动以查看其内容

问题: 我有一个内部iFrame,里面有我无法控制的第三方广告。如果内部iFrame运行以下任何Javascript命令,则外部页面向下滚动所有内容以查看内部iFrame:

  • 模糊并聚焦其中的元素
  • window.location.href或document.location.hash指向其中的锚点

  • 滚动查看其中的元素

  • (等待5秒钟,使其启动)

    无效的解决方案:

  • 如果我控制了外部页面,我可以监听onScroll事件,如果不是鼠标滚轮或键向上/向下事件,我可以防止页面滚动。但是,由于安全原因,我的外部iFrame无法访问主页或阻止主页向上或向下滚动
  • 我可以覆盖上面提到的所有Javascript方法,这样它们就不起作用了——然而,我的内部iFrame中的广告实际上创建了它们自己的内部iFrame,这些iFrame具有该功能,并导致了相同的问题
  • 没有向上传播的事件,我可以看到哪个iFrame无法到达主页。浏览器似乎直接侦听最内部的iFrame

  • 也许还有其他一些方法可以解决这个问题,但一个非常简单的解决方案是通过将麻烦的iFrame定位为
    已修复的
    将其从站点的自然布局中移除

    那么剩下的唯一挑战可能是迫使他们表现得好像他们是自然布局的一部分。但与原始问题相比,该任务的复杂性似乎一般


    此外,在您的特定情况下,上述方法非常现成。由于外部iframe不可滚动,且其高度与内容高度相匹配:您只需为每个iframe插入一个与其对应大小相匹配的占位符…

    如果您可以删除IE10和以下支持,并且
    iframe
    是同一个域,则可以使用解决方案2的组合(重写方法)和
    突变
    事件。 您需要首先遍历DOM中已经存在的所有
    iframe
    ,删除不需要的函数,还可能清除不需要的间隔。在每个
    文档
    上添加一个
    变异
    观察者
    ,该观察者将在
    添加的节点
    上运行相同的脚本(如果它们是
    iFrame
    )。因此,您将有一个递归函数在开始时遍历所有iFrame,还有一个函数用于删除方法、清除间隔并在每个
    iFrame
    上添加观察者。一旦添加了一个
    iFrame
    ,您就可以在它上面运行相同的东西。类似于这样:

    递归函数:

    var to_cancel = ["scrollIntoView","blur","focus"];
    window.onload = function(){iterate_window_object(window)};
    function iterate_window_object(cur_win){
        remove_methods(cur_win);
        for(var i=0;i<cur_win.frames.length;i++){
            remove_methods(cur_win.frames[i])
             if(cur_win.frames[i].length>0){
                  iterate_window_object(cur_win.frames[i])
               }
    
          }
       }
    
    function remove_methods(cur_win){ 
          for(var j=0;j<to_cancel.length;j++){
               cur_win.Element.prototype[to_cancel[j]] = {}
           }
    
           for (var k = 0; k < 999;k++){
                cur_win.clearInterval(k);
           }
           cur_win.setInterval = {};
           cur_win.observer = new MutationObserver(function(mutations) {
                 mutations.forEach(function(mutation) {
                      for(var k=0;k<mutation.addedNodes.length;k++){
                           var added_node = mutation.addedNodes[k]
                           if(added_node.tagName == "IFRAME"){
                                remove_methods(added_node.contentWindow);
                                added_node.contentWindow.onload = function(){iterate_window_object(added_node.contentWindow)};
                            }
                       };
                    });    
                });
                cur_win.config = { childList: true };
                  cur_win.observer.observe(cur_win.document.getElementsByTagName('body')[0], cur_win.config);
    
            }
    
    var to_cancel=[“滚动视图”、“模糊”、“聚焦”];
    window.onload=function(){iterate\u window\u object(window)};
    函数迭代窗口对象(cur\u win){
    删除方法(cur_-win);
    对于(var i=0;i0){
    迭代窗口对象(cur\u win.frames[i])
    }
    }
    }
    
    清洁功能:

    var to_cancel = ["scrollIntoView","blur","focus"];
    window.onload = function(){iterate_window_object(window)};
    function iterate_window_object(cur_win){
        remove_methods(cur_win);
        for(var i=0;i<cur_win.frames.length;i++){
            remove_methods(cur_win.frames[i])
             if(cur_win.frames[i].length>0){
                  iterate_window_object(cur_win.frames[i])
               }
    
          }
       }
    
    function remove_methods(cur_win){ 
          for(var j=0;j<to_cancel.length;j++){
               cur_win.Element.prototype[to_cancel[j]] = {}
           }
    
           for (var k = 0; k < 999;k++){
                cur_win.clearInterval(k);
           }
           cur_win.setInterval = {};
           cur_win.observer = new MutationObserver(function(mutations) {
                 mutations.forEach(function(mutation) {
                      for(var k=0;k<mutation.addedNodes.length;k++){
                           var added_node = mutation.addedNodes[k]
                           if(added_node.tagName == "IFRAME"){
                                remove_methods(added_node.contentWindow);
                                added_node.contentWindow.onload = function(){iterate_window_object(added_node.contentWindow)};
                            }
                       };
                    });    
                });
                cur_win.config = { childList: true };
                  cur_win.observer.observe(cur_win.document.getElementsByTagName('body')[0], cur_win.config);
    
            }
    
    函数删除方法(cur\u-win){
    
    对于(var j=0;jc您能尝试沙箱化子iframe吗?我意识到这可能不是一个解决方案,因为ads最有可能需要运行脚本,但可能值得尝试?也许在加载iframe内容后添加一个沙箱属性?是的,我试过了,唯一有效的沙箱设置似乎是完全禁用javascript,这不是一个选项在上,因为广告需要运行脚本,但IFRAME op唯一可以控制的是内部IFRAME,我认为这并不重要enough@YuriyGalanter据我所知,内部iframe包含广告,可能会出现不正常行为,外部iframe由op控制,最重要的上下文不在他的控制范围内。我创建了这样一个设置,结果看起来很有希望。如果我正确理解了外部框架的HTML内容是由OP控制的,而不是外部主页面中外部IFRAME的定义方式。可能是错误的想法!将内部IFRAME更改为固定位置完全可以消除问题。你关于在那里放置占位符的想法也是一个好主意,我意识到我们可以使用Javascript动态地将固定iFrame的顶部设置为虚拟元素的顶部,以便它仍然显示在外部iFrame中的相同位置。哇-非常感谢您提供了完整的答案!我没有测试它,因为Artur的工作非常简单,但似乎这也可以工作。