¿Puedo usar window.location.replace en un iframe?


15

¿Podemos usar window.location.replacepara evitar el historial y apuntar a anclajes en la página sin recargar páginas, pero no en iframes?

El problema es una violación de CSP (política de seguridad de contenido), que los estados script-src 'unsafe-inline'deben estar habilitados. Excepto que no tengo un CSP definido, e incluso si defino uno y lo permito script-src 'unsafe-inline', todavía aparece el mismo error de violación. Mismo resultado en ie11 / chrome / ff.

Iframe en el mismo dominio (en el mismo directorio).

  1. Apunte al iframe en la consola y úselo en la window.location.replace('/samepage.html#onpage_anchor')consola.
  2. funciona. Se dirige al ancla en la página sin volver a cargar la página y sin historial.
  3. Ponga el mismo código en línea en los enlaces de anclaje y funciona.
  4. Use el mismo código en un script externo, obtenga el error de violación de csp. Esto funciona bien si no en un iframe.

Intenté crear un CSP para permitir la acción, pero ni siquiera las políticas de seguridad de contenido más permisivas posibles lo permitirían.


Editar: así que reuní ejemplos en plunker que permiten múltiples archivos para poder usar hrefs adecuados que hacen referencia a las páginas padre / hijo.

Notas sobre los ejemplos de plunker:

  1. El problema no se reproduce en estos ejemplos. El guión funciona perfectamente, incluso en el iframe. Sin embargo, el mismo código no funciona en mi servidor local, o cuando lo ejecuto en vivo en un VPS.

  2. Sospecho que la violación de CSP no se activa en plunker porque plunker presenta contenido al navegador a través de una especie de capa de abstracción de algún tipo.

  3. La primera vez que hace clic en los enlaces de acordeón en el padre, se actualiza. Esto se debe a que la forma en que la página se carga inicialmente no hace referencia a index.html. Los clics posteriores funcionan como se espera sin recargar la página. No es un problema en el iframe porque inicialmente hace referencia a child.html

  4. Estos son buenos ejemplos para mostrar el código sin requerir modificaciones para que funcione (como en la necesidad de cambiar los hrefs para que funcionen en fragmentos de stackoverflow, mencionados a continuación). También es bueno, ya que muestra que JavaScript funciona como debería. Pero no muestra el problema real. Aún tendrá que cargarlo en su editor y ejecutarlo en un servidor local o entorno de alojamiento en vivo para ver el problema real.

Ejemplos de Plunker

Con guión: Sin historia
Sin guión: Con historia


Ejemplo de código simplificado

Acordeón simple con una entrada. Suficiente para reproducir el problema.

Al hacer clic en abrir / cerrar se ampliará / colapsará el acordeón, no se requiere JS. El JS debería hacer exactamente lo mismo pero sin historia. Funciona bien, pero no en un iframe.

Notas de fragmentos de código:

  1. Puede ejecutar el fragmento para tener una idea de lo que estoy describiendo, pero en realidad no demuestra el problema.

  2. El fragmento no se comporta como lo haría en un navegador real, el javascript no funciona.

  3. El fragmento muestra el código, pero debe ejecutarse en un iframe para ver el problema. Ejecútelo fuera de un iframe para ver la diferencia y cómo debería funcionar.

  1. Debido a cómo funcionan los enlaces con el JS (reemplazando la url completa), en realidad deben ser así en href="https://stackoverflow.com/thispage.html#ac1"lugar de solo href="#ac1"como aparecen en el fragmento (no pueden orientar la página html real en el fragmento). Entonces, si intenta esto en su editor (por favor hágalo), recuerde cambiar los enlaces a este formato this_document.html#anchor para que sigan siendo los mismos anclajes de página, pero el page.html está incluido en el enlace.


La secuencia de comandos

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

    });

Esto es muy simple:
1. La función acAnch toma el hrefatributo y lo coloca en window.location.replace().
2. Escuche los clics en las anclas dentro del acordeón para ejecutar la función acAnch.

Entonces todo lo que hace el script es ejecutar window.location.replace('/this_same_page.html#on_page_anchor')

Si pones eso en la consola, funciona, no hay violación de CSP. Pero ejecutarlo desde un script externo no funciona.

Inline en los enlaces funciona bien:

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

Poner eso en los enlaces respectivos funciona perfectamente , pero realmente prefiero no usar un script en línea como ese. Debe haber una manera de hacer esto con un script externo.

Intenté ejecutar el javascript en padre en lugar de en el iframe (con modificaciones para seleccionar los enlaces dentro del niño, por supuesto). El mismo resultado de error CSP.


¿Por qué estoy haciendo esto?

Bueno, el sitio es mucho más complejo que el ejemplo. Las anclas en iframes funcionan bien pero agregan historia. Si ejecuta el código anterior sin el javascript (o simplemente ejecuta el fragmento), abra y cierre el acordeón varias veces y use el botón Atrás, volverá a los estados de cierre abierto.

No me importaría el historial, pero si está en un iframe, cuando abandonas la página principal y luego vuelves a él, el historial en el iframe está roto. Retroceder ya no atraviesa los estados de acordeón, sino que solo sigue recargando el iframe. Inicialmente, los anclajes no causan recargas de iframe, sino que solo atraviesan el historial del estado del acordeón, que funciona bien, hasta que abandonas la página y vuelves. Luego, atrás ya no pasa por los estados de acordeón, sino que pasa por una pila de recargas de iframe idénticas. Es un comportamiento muy hostil para el usuario.

No necesito usar location.replace si hay otro método que funcione. Sin embargo, he probado muchos otros enfoques, y he descubierto que los métodos que pueden lograr el mismo resultado, generalmente dan como resultado el mismo error.

El objetivo es simplemente activar los enlaces de anclaje en la página sin recargar, y sin historial, dentro de un iframe.

El guión en línea funciona. ¿Podemos hacer que funcione en un archivo externo .js?


¿Estás tratando de llegar al ancla? Si es así, <a href="#ac0" class="ac-close">Close</a>debería funcionar.
Demenciales

De acuerdo, configuré ejemplos en plunker. Desafortunadamente, el problema no se reproduce en plunker. Más bien, el guión funciona bien, incluso en un iframe. con guión: sin historia y sin guión tiene historia . Problema menor sobre el saqueador; los enlaces de acordeón en el padre provocan una actualización de la página, solo la primera vez que se hace clic (inicialmente se carga sin referencia index.html, por lo que después del primer clic, funciona como se esperaba, sin recargar la página). No es un problema para el iframe, ya que está cargado con el child.html src.
Veneseme Tyras el

Entonces, al menos con los ejemplos de plunker, puede ver el código completo y ver cómo debería funcionar. Sin embargo, no funciona en mi servidor local o cuando lo ejecuto en vivo en un VPS. Actualizaré la pregunta con los enlaces y la información del plunker.
Veneseme Tyras el

1
Llevé su código de muestra a mi servidor, funciona bien, luego creé un nuevo ejemplo de plunker a partir de su ejemplo plnkr.co/edit/V3kx7LQbTppaQ6V06uZp?p=preview , también funciona bien. No hay resultado de error CSP.
Pensador

Sí, bueno, funciona bien en el saqueador que hice también. Sin embargo, tengo curiosidad por saber cómo funciona en su servidor, porque después de su comentario lo verifiqué tres veces y no puedo hacer que funcione en mi servidor en vivo o en mi servidor local.
Veneseme Tyras el

Respuestas:



Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.