最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to prevent iFrame actions from causing outer page to scroll to it - Stack Overflow

programmeradmin5浏览0评论

First, I know there are many questions about this phenomenon but none of the workarounds given so far would help in the situation I have here.

Environment: My code is in the Outer iFrame inside a page I don't control. It's sized to fit all my content so no scrolling happens inside my iFrame. Rather, the outer page can scroll it up and down to view its content.

Problem: I have an inner iFrame holding third party ads which I can't control. If the inner iFrame runs any of the following Javascript mands, the outer page scrolls everything down to bring the inner iFrame into view:

  1. blur and focus on an element inside it
  2. window.location.href or document.location.hash to an anchor inside it.

  3. scrollIntoView on an element inside it

Here is a demo a colleague put together (wait 5 seconds for it to start)

Solutions that don't work:

  1. If I controlled the outer page, I could listen to the onScroll event and prevent the page from scrolling if it wasn't from a mousewheel or key up/down event. However, due to security reasons, my outer iFrame can't access the main page or prevent the main page from scrolling it up or down.
  2. I could overwrite all those Javascript methods mentioned above so they didn't work - however, the ads in my inner iFrame actually create their own internal iFrames which have that functionality and causes the same issue.
  3. There are no events being propagated up that I can see which my iFrame could stop from reaching the main page. The browser appears to listen directly to the innermost iFrame.

First, I know there are many questions about this phenomenon but none of the workarounds given so far would help in the situation I have here.

Environment: My code is in the Outer iFrame inside a page I don't control. It's sized to fit all my content so no scrolling happens inside my iFrame. Rather, the outer page can scroll it up and down to view its content.

Problem: I have an inner iFrame holding third party ads which I can't control. If the inner iFrame runs any of the following Javascript mands, the outer page scrolls everything down to bring the inner iFrame into view:

  1. blur and focus on an element inside it
  2. window.location.href or document.location.hash to an anchor inside it.

  3. scrollIntoView on an element inside it

Here is a demo a colleague put together (wait 5 seconds for it to start)

Solutions that don't work:

  1. If I controlled the outer page, I could listen to the onScroll event and prevent the page from scrolling if it wasn't from a mousewheel or key up/down event. However, due to security reasons, my outer iFrame can't access the main page or prevent the main page from scrolling it up or down.
  2. I could overwrite all those Javascript methods mentioned above so they didn't work - however, the ads in my inner iFrame actually create their own internal iFrames which have that functionality and causes the same issue.
  3. There are no events being propagated up that I can see which my iFrame could stop from reaching the main page. The browser appears to listen directly to the innermost iFrame.
Share Improve this question asked Jun 12, 2015 at 18:28 David DaudelinDavid Daudelin 6111 gold badge7 silver badges17 bronze badges 2
  • Can you try sandboxing the child iframe? I realize this is probably not a solution since ads most likely need to run scripts, but perhaps worth experimenting? Perhaps add a sandbox attribute after iframe content loaded? – Yuriy Galanter Commented Jun 12, 2015 at 19:25
  • Yeah I tried that and the only sandboxing setting that seems to work is totally disabling javascript which isn't an option since the ads need to run scripts – David Daudelin Commented Jun 12, 2015 at 21:29
Add a ment  | 

2 Answers 2

Reset to default 4 +50

Maybe there are some other ways to solve this issue, but one pretty straightforward solution is to take troublesome iframes out of the natural layout of the site by positioning them as fixed.

Then the only remaining challenge may be to force them to behave as if they were part of the natural layout. But this tasks seems to be of mediocre plexity in parison to the original problem.

Moreover, in your particular case, the above approach works pretty out of the box. Since the outer iframe is not scrollable and its height matches its content height: you just need to insert -- for each iframe -- a placeholder that matches its counterpart size...

If you can drop IE10 and below support and the iframes are same domain, you could use a bination of you solution number 2 (rewrite the methods) and mutation events. You'd need to first iterate through all iFrames already in the DOM and remove unwanted functions, and maybe also clear unwanted intervals. And on each document you add a mutation observer that will run the same scripts on added nodes if they are iFrames. So you'd have a recursive function going through all iframes at the beginning, and a function to remove methods, clear intervals and add observers on each iFrame. And once an iFrame is added, you run the same thing on it.Something like this:

The recursive function:

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

      }
   }

The cleaning function:

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

        }

There's probably a way to make it look better, the hardest part is being able to modify the methods before they get called. And here it's a bit overkill because it iterates through new iFrames so that if an iframe is added with already added iFrames, they are also taken car of. It's probably not necessary. So it could maybe be a solution, but mutation events aren't supported by IE10 and below.

发布评论

评论列表(0)

  1. 暂无评论