2015-06-12 17 views
12

Innanzitutto, so che ci sono molte domande su questo fenomeno ma nessuno dei rimedi proposti fino ad ora potrebbe aiutare nella situazione che ho qui.Come impedire che le azioni iFrame provochino lo scorrimento della pagina esterna

enter image description here

Ambiente: mio codice è in Outer iFrame all'interno di una pagina non mi controllo. È dimensionato per adattarsi a tutti i miei contenuti in modo che non avvenga lo scorrimento all'interno del mio iFrame. Piuttosto, la pagina esterna può scorrere su e giù per visualizzare il suo contenuto.

Problema: Ho un iFrame interno contenente annunci di terze parti che non posso controllare. Se l'iFrame interno corre una delle seguenti Javascript comandi, la pagina esterna scorre tutto giù per portare l'iFrame interna in vista:

  1. sfocatura e concentrarsi su un elemento interno
  2. window.location.href o document.location.hash a un'ancora al suo interno.

  3. scrollIntoView su un elemento interno

Here is a demo a colleague put together (attendere 5 secondi per poter iniziare)

Soluzioni che non funzionano:

  1. Se ho controllato la pagina esterna, potrei ascoltare l'evento onScroll e impedire alla pagina di scorrere se non fosse da una rotellina del mouse o da un tasto su/giù. Tuttavia, a causa di motivi di sicurezza, il mio iFrame esterno non può accedere alla pagina principale o impedire alla pagina principale di scorrere verso l'alto o verso il basso.
  2. Potrei sovrascrivere tutti quei metodi Javascript menzionati sopra in modo che non funzionassero, tuttavia gli annunci nel mio iFrame interno creano effettivamente i propri iFrame interni che hanno quella funzionalità e causano lo stesso problema.
  3. Non ci sono eventi propagati che posso vedere quale il mio iFrame potrebbe smettere di raggiungere la pagina principale. Il browser sembra ascoltare direttamente l'iFrame più interno.
+0

Puoi provare a sandboxing l'iframe bambino? Mi rendo conto che probabilmente non è una soluzione, dal momento che gli annunci probabilmente hanno bisogno di eseguire script, ma forse vale la pena sperimentarli? Forse aggiungere un attributo sandbox dopo aver caricato il contenuto iframe? –

+0

Sì, l'ho provato e l'unica impostazione sandbox che sembra funzionare disabilita totalmente javascript che non è un'opzione dal momento che gli annunci devono eseguire script –

risposta

3

Forse ci sono altri modi per risolvere questo problema, ma una soluzione piuttosto semplice è quello di prendere iframe fastidiosi fuori la disposizione naturale del sito da posizionandoli come fixed.

Quindi l'unica sfida rimanente potrebbe essere quella di forza da comportarsi come se fossero parte del layout naturale. Ma questo compito sembra essere di mediocre complessità rispetto al problema originale.

Inoltre, nel vostro caso particolare, l'approccio di cui sopra funziona piuttosto fuori dagli schemi. Dato che l'iframe esterno non è scorrevole e la sua altezza corrisponde all'altezza del contenuto: devi solo inserire - per ogni iframe - un segnaposto che corrisponda alla sua controparte ...

+0

Ma l'unico IF di IFRAME può controllare è iframe interno, e non penso che sia abbastanza –

+0

@YuriyGalanter da quello che ho capito gli iframe interni contengono pubblicità e possono comportarsi male, l'iframe esterno è controllato da op e il contesto più importante è al di fuori del suo controllo. Ho creato un ambiente simile e il risultato sembra piuttosto promettente. –

+0

Se capisco correttamente, il contenuto HTML della cornice esterna è controllato dall'OP, non come IFRAME esterno è definito nella pagina esterna principale. Potrebbe essere sbagliato però –

1

Se riesci a rilasciare IE10 e sotto supporto e lo iframes è lo stesso dominio, è possibile utilizzare una combinazione della soluzione numero 2 (riscrittura dei metodi) e degli eventi mutation. Dovresti prima eseguire l'iterazione su tutto lo iFrames già nel DOM e rimuovere le funzioni indesiderate, e forse anche cancellare gli intervalli indesiderati. E su ogni document si aggiunge uno mutationobserver che eseguirà gli stessi script su added nodes se sono iFrames. Quindi avresti una funzione ricorsiva che attraversa tutti gli iframe all'inizio e una funzione per rimuovere metodi, intervalli chiari e aggiungere osservatori su ciascuno iFrame. E una volta che si aggiunge un iFrame, si esegue la stessa cosa su it.Something come questo:

La funzione ricorsiva:

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

     } 
    } 

La funzione di pulizia:

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

     } 

C'è probabilmente un modo per fallo sembrare migliore, la parte più difficile è riuscire a modificare i metodi prima che vengano chiamati. E qui è un po 'eccessivo perché itera attraverso il nuovo iFrames in modo che se un iframe viene aggiunto con già aggiunto iFrames, vengono presi anche auto di. Probabilmente non è necessario. Quindi potrebbe essere una soluzione, ma gli eventi mutation non sono supportati da IE10 e seguenti.

+0

Wow - grazie mille per la risposta completa! Non l'ho provato da quando Artur ha lavorato in modo così semplice, ma sembra che anche questo funzionerebbe. –

Problemi correlati