Posso usare window.location.replace in un iframe?


15

Possiamo usare window.location.replaceper evitare la cronologia e per indirizzare gli ancoraggi nella pagina senza ricaricare la pagina, ma non negli iframe?

Il problema è una violazione CSP (content security policy), che afferma che script-src 'unsafe-inline'deve essere abilitato. Tranne per il fatto che non ho definito un CSP, e anche se ne definisco uno e lo autorizzo, script-src 'unsafe-inline'si ottiene sempre lo stesso errore di violazione. Stesso risultato in ie11 / chrome / ff.

Iframe sullo stesso dominio (nella stessa directory).

  1. Scegli come target l'iframe nella console e utilizzalo window.location.replace('/samepage.html#onpage_anchor')nella console.
  2. Funziona. Prende di mira l'ancoraggio sulla pagina senza ricaricare la pagina e senza cronologia.
  3. Inserisci lo stesso codice in linea sui collegamenti di ancoraggio e funziona.
  4. Usa lo stesso codice in uno script esterno, ottieni l' errore di violazione csp. Funziona bene se non in un iframe.

Ho provato a creare un CSP per consentire l'azione, ma nemmeno le politiche di sicurezza dei contenuti più permissive possibili lo permetterebbero.


Modifica: così ho messo insieme degli esempi su plunker che consente più file in modo da poter utilizzare href appropriati che fanno riferimento alle pagine padre / figlio.

Note sugli esempi di plunker:

  1. Il problema non è riprodotto in questi esempi. La sceneggiatura funziona perfettamente, anche nell'iframe. Tuttavia, lo stesso codice non funziona sul mio server locale o quando lo eseguo dal vivo su un VPS.

  2. Sospetto che la violazione del CSP non venga attivata sul plunker perché il plunker presenta il contenuto al browser tramite una sorta di livello di astrazione di qualche tipo.

  3. La prima volta che si fa clic sui collegamenti a fisarmonica nel genitore, viene eseguito un aggiornamento. Questo perché il modo in cui la pagina inizialmente la carica non fa riferimento a index.html. I clic successivi funzionano come previsto senza ricaricare la pagina. Non è un problema nell'iframe perché inizialmente fa riferimento a child.html

  4. Questi sono buoni esempi per mostrare il codice senza richiedere modifiche per farlo funzionare (come nella necessità di cambiare gli href per farli funzionare negli snippet di stackover, menzionati di seguito). È anche buono in quanto mostra che JavaScript funziona come dovrebbe. Ma non mostra il problema reale. Dovrai comunque caricarlo nel tuo editor ed eseguirlo su un server locale o in un ambiente di hosting live per vedere il vero problema.

Esempi di Plunker

Con sceneggiatura: senza storia
Senza sceneggiatura: con storia


Esempio di codice semplificato

Fisarmonica semplice con una voce. Sufficiente per riprodurre il problema.

Facendo clic su apri / chiudi si espanderà / comprimerà la fisarmonica, non è richiesto alcun JS. Il JS dovrebbe fare esattamente la stessa cosa ma senza storia. Funziona bene, ma non in un iframe.

Note sullo snippet di codice:

  1. Puoi eseguire lo snippet per avere un'idea di ciò che sto descrivendo, ma in realtà non dimostra il problema.

  2. Lo snippet non si comporta come in un browser reale, il javascript non funziona.

  3. Lo snippet mostra il codice, ma dovrebbe essere eseguito in un iframe per vedere il problema. Eseguilo all'esterno di un iframe per vedere la differenza e come dovrebbe funzionare.

  1. A causa del modo in cui i collegamenti funzionano con JS (sostituendo l'intero URL), in realtà devono essere così href="https://stackoverflow.com/thispage.html#ac1"piuttosto che href="#ac1"come appaiono nello snippet (non possono scegliere come target la pagina html effettiva nello snippet). Quindi se provi questo nel tuo editor (per favore), ricordati di cambiare i collegamenti in questo formato in this_document.html#anchor modo che siano ancora gli stessi ancoraggi di pagina, ma page.html è incluso nel collegamento.


Il copione

$(document).ready(function() {

      // anchor links without history
      $.acAnch = function(event) {
        event.preventDefault();
        var anchLnk = $(event.target);
        var anchTrgt = anchLnk.attr('href');
        window.location.replace(anchTrgt);
      }
      // listen for anchor clicks
      $('.accordion').on('click', 'a', $.acAnch);

    });

Questo è molto semplice:
1. La funzione acAnch accetta l' hrefattributo e lo rilascia window.location.replace().
2. Ascolta i clic sugli ancoraggi all'interno della fisarmonica per eseguire la funzione acAnch.

Quindi viene eseguito tutto lo script window.location.replace('/this_same_page.html#on_page_anchor')

Se lo metti nella console funziona, nessuna violazione CSP. Ma eseguirlo da script esterni non funziona.

In linea sui collegamenti funziona bene:

onclick="event.preventDefault();window.location.replace('/thispage.html#acc0');"
onclick="event.preventDefault();window.location.replace('/thispage.html#acc1');"

Metterlo sui rispettivi collegamenti funziona perfettamente , ma preferisco davvero non usare uno script inline come quello. Ci deve essere un modo per farlo con uno script esterno.

Ho provato a eseguire il javascript sul genitore invece che nell'iframe (con modifiche per selezionare i collegamenti all'interno del figlio ovviamente). Stesso risultato dell'errore CSP.


Perché lo sto facendo?

Bene, il sito è molto più complesso dell'esempio. Le ancore negli iframe funzionano bene ma aggiungono la cronologia. Se esegui il codice sopra senza javascript (o semplicemente esegui lo snippet), apri e chiudi la fisarmonica alcune volte e usi il pulsante Indietro, tornerà indietro negli stati di chiusura aperti.

Non mi dispiacerebbe la cronologia, ma se si trova in un iframe, quando lasci la pagina principale e poi ritorni ad essa, la cronologia nell'iframe viene interrotta. Tornare indietro non attraversa più gli stati della fisarmonica, ma continua a ricaricare l'iframe. Inizialmente le ancore non causano ricariche iframe ma passano attraverso la storia dello stato della fisarmonica, che funziona benissimo, fino a quando non lasci la pagina e torni indietro. Quindi la schiena non passa più attraverso gli stati della fisarmonica, ma passa attraverso una pila di ricariche identiche di iframe. È un comportamento molto ostile da parte dell'utente.

Non ho bisogno di usare location.replace se esiste un altro metodo che funzionerà. Ho provato molti altri approcci, tuttavia, e ho scoperto che i metodi che possono ottenere lo stesso risultato, generano generalmente lo stesso errore.

L'obiettivo è semplicemente attivare i collegamenti di ancoraggio sulla pagina senza ricaricare, e senza cronologia, all'interno di un iframe.

Lo script inline funziona. Possiamo farlo funzionare in un file .js esterno?


stai solo cercando di raggiungere l'ancora? in tal caso, <a href="#ac0" class="ac-close">Close</a>dovrebbe funzionare.
Demenza

Ok, ho installato degli esempi su plunker. Sfortunatamente, il problema non è riprodotto sul plunker. Piuttosto, la sceneggiatura funziona bene, anche in un iframe. con sceneggiatura - nessuna storia e senza sceneggiatura ha storia . Problema minore sul plunker; i collegamenti a fisarmonica sul genitore causano un aggiornamento della pagina, solo la prima volta che si fa clic (inizialmente il caricamento viene effettuato senza riferimento index.html, quindi dopo il primo clic funziona come previsto, senza ricaricare la pagina). Non è un problema per l'iframe poiché viene caricato con il file child.html src.
Veneseme Tyras,

Quindi almeno con gli esempi di plunker puoi vedere il codice completo e vedere come dovrebbe funzionare. Tuttavia, non funziona sul mio server locale o quando lo eseguo dal vivo su un VPS. Aggiornerò la domanda con i collegamenti e le informazioni del plunker.
Veneseme Tyras,

1
Ho portato il tuo codice di esempio sul mio server che funziona bene, quindi ho creato un nuovo esempio di plunker dal tuo esempio plnkr.co/edit/V3kx7LQbTppaQ6V06uZp?p=preview funziona anche bene. Nessun risultato di errore CSP.
Pensatore

Sì, bene funziona bene anche sul plunker che ho fatto. Sono curioso di sapere come funziona sul tuo server, perché dopo il tuo commento ho controllato tre volte e non riesco a farlo funzionare sul mio server live o sul mio server locale.
Veneseme Tyras,

Risposte:



Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.