web-dev-qa-db-fra.com

Puis-je utiliser window.localisation.replace dans un iframe?

Nous pouvons utiliser window.location.replace To éviter l'historique, et to cible ancrages sur page sans recharge de page, = mais * pas dans les iframes?

Le problème est une violation du CSP (Politique de sécurité de contenu), qui indique script-src 'unsafe-inline' Doit être activé. Sauf que je n'ai pas de csp défini, et même si je définis un et autorisez script-src 'unsafe-inline' Cela donne toujours la même erreur de violation. Même résultat dans IE11/chrome/ff.

iframe sur le même domaine (dans le même répertoire).

  1. Ciblez l'iframe dans la console et utilisez window.location.replace('/samepage.html#onpage_anchor') dans la console.
  2. Ça marche. Il cible l'ancre à la page sans recharger la page et sans historique.
  3. Mettez le même code en ligne sur les liens d'ancrage et cela fonctionne.
  4. Utilisez le même code dans le script externe, obtenez l'erreur de violation du CSP. Cela fonctionne bien si pas dans un iframe.

J'ai essayé de créer un CSP pour permettre l'action, mais pas même les politiques de sécurité de contenu les plus permissives qui lui permettraient.

J'ai donc mis ensemble des exemples sur PLUCKER qui permettent plusieurs fichiers afin que je puisse utiliser des hrefs appropriés qui font référence aux pages parent/enfant.

Notes sur les exemples de plumker:

  1. Le problème n'est pas reproduit dans ces exemples. Le script fonctionne parfaitement, même dans l'iframe. Cependant, le même code ne fonctionne pas sur mon serveur local ou lorsque je l'exécute en direct sur un VPS.
  2. Je soupçonne que la violation du CSP ne soit pas déclenchée sur PLUCKER car Plunker présente le contenu du navigateur via une sorte de couche d'abstraction de quelque sorte.
  3. La première fois que vous cliquez sur les liens d'accordéon dans le parent, il provoque une actualisation. C'est parce que la façon dont la page charge initialement cela ne fait pas référence à index.html. Les clics suivants fonctionnent comme prévu sans rechargement de page. Pas un problème dans l'iframe car il fait initialement une référence enfantine.html
  4. Ce sont de bons exemples pour montrer le code sans nécessiter des modifications nécessaires pour le faire fonctionner (comme dans la nécessité de changer les HREFS pour les faire fonctionner dans les extraits Stackoverflow, mentionné ci-dessous). C'est aussi bon comme Il montre le JavaScript qui fonctionne comme il se doit. Mais cela ne montre pas le problème réellement. Vous aurez toujours besoin de le charger dans votre éditeur et de l'exécuter sur un serveur local ou d'un environnement d'hébergement en direct pour voir le problème réel.

Exemples de PLUCKER: avec script/sans historique . Sans script/avec historique


Accordéon simple avec une entrée. Suffisant pour reproduire la question.

En cliquant sur Open/Fermer, expandir/effondrer sera accordéon, pas de JS requis. Le JS devrait faire exactement la même chose mais sans histoire. Fonctionne bien, mais pas dans un iframe.

NOTES DE CODE SNIPPET:

  1. Vous pouvez exécuter l'extrait pour avoir une idée de ce que je décris, mais cela ne démontre pas la question.

  2. L'extrait ne se comporte pas comme ça dans un vrai navigateur, le JavaScript ne fonctionne pas.

  3. L'extrait montre le code, mais il devrait être exécuté dans un iframe pour voir le problème. Exécutez-le en dehors d'un iframe pour voir la différence et comment cela devrait fonctionner.

  4. En raison de la manière dont les liens fonctionnent avec le JS (remplaçant l'URL entière), ils sont en fait DOIVEMENT Soyez comme ceci href="/thispage.html#ac1" Plutôt que simplement href="#ac1" Comme ils apparaissent dans l'extrait ( Impossible de cibler la page HTML réelle dans l'extrait de l'extrémité). Donc, si vous Essayez ceci dans votre éditeur(veuillez le faire), Alors rappelez-vous de Modifiez les liens vers ce formatthis_document.html#anchor Donc, ils sont toujours Même ancrages de page, Mais le page.html est inclus dans le lien.

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

});
div#sample.example .accordion {
  margin-left: 50px;
  margin-top: 50px;
}

div#sample.example section {
  box-sizing: border-box;
  clear: both;
  position: relative;
  display: block;
  width: 300px;
  height: 32px;
  padding: 0;
  background-color: #fff;
  box-shadow: inset 0 0 1px 1px #000;
  overflow: hidden;
}

div#sample.example section:target {
  height: auto;
}

div#sample.example a {
  box-sizing: border-box;
  display: block;
  float: right;
  width: 50%;
  height: 32px;
  margin: 0;
  padding: 4px;
  text-align: center;
  font-size: 16px;
  color: #000;
  background-color: #fff;
  box-shadow: inset 0 0 1px 1px #000;
}

div#sample.example p {
  box-sizing: border-box;
  clear: both;
  display: block;
  width: 100%;
  padding: 16px;
  margin: 16px 0 0;
  text-align: center;
  color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="sample" class="example">
  <article class="accordion">
    <section id="ac1">
      <a href="#ac0" class="ac-close">Close</a>
      <a href="#ac1" class="ac-open">Open</a>
      <div class="ac-content">
        <p>The elephants talking in their sleep kept me up so late.</p>
      </div>
    </section>
  </article>
</div>
$(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);

    });

C'est très simple:

  1. la fonction Acanch prend l'attribut href et le dépose dans window.location.replace().
  2. Écoutez des clics sur les ancrages dans l'accordéon pour exécuter la fonction Acanch.

Donc, tout le script est exécuté window.location.replace('/this_same_page.html#on_page_anchor')

Si vous mettez cela dans la console, cela fonctionne, pas de violation du CSP. Mais le fonctionnement du script externe ne fonctionne pas.

Inline sur les liens fonctionne bien:

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

Mettre cela sur les liens respectifs fonctionne parfaitement, mais je préfère vraiment ne pas utiliser de script en ligne comme ça. Il doit y avoir un moyen de le faire avec un script externe.

J'ai essayé d'exécuter le javascript sur le parent au lieu de l'iframe (avec des modifications pour sélectionner les liens dans l'enfant bien sûr). Même résultat d'erreur csp.

Pourquoi est-ce que je fais cela? Eh bien, le site est beaucoup plus complexe que l'exemple. Les ancres dans les iframes fonctionnent bien, mais elles Ajouter l'historique. Si vous exécutez le code ci-dessus sans le JavaScript, ouvrez et fermez l'accordéon à quelques reprises, et utilisez le bouton arrière , il reviendra dans les états proches ouverts.

Cela ne me dérangerait pas l'histoire , Mais si c'est dans un iframe, lorsque vous quittez la page parent, puis revenez-y, l'histoire de l'iframe est cassée. Retour ne revient plus dans les États de l'accordéon, mais il ne cesse de recharger l'Iframe. Initialement, les ancrages ne provoquent pas les recharges iframe, mais seulement des étapes de l'histoire de l'état d'accordéon, qui fonctionne bien, jusqu'à ce que vous quittiez la page et revenez. Puis de retour ne traverse plus les États d'accordéon, mais passe simplement par une pile de recharges iframe identiques. C'est un comportement hostile très utilisateur.

Je n'ai pas besoin d'utiliser l'emplacement.replace s'il y a une autre méthode qui fonctionnera. J'ai bien essayé de nombreuses autres approches et j'ai découvert que des méthodes pouvant atteindre le même résultat, entraînent généralement la même erreur.

L'objectif est simplement d'activer les liens d'ancrage à la page sans rechargement et sans historique, à l'intérieur d'une iframe.

Le script en ligne fonctionne. Pouvons-nous le faire fonctionner dans un fichier externe ?js?

24
Veneseme Tyras

oui, vous pouvez, voici un exemple en direct du lien ci-dessous

 https://codepen.io/pmk/pen/wOwoyW

Html

<div class="">
<h3>Testing 4 methods of writing dynamic content to Iframe.</h3>
<p>#1 use <strong>document.write()</strong>, 
#2 use    <strong>URL.createObjectURL()</strong>, 
#3 use <strong>encodeURI()</strong> and #4  <strong>iframe.srcdoc</strong></p>
<p>Using the recommended method <strong>URL.createObjectURL()</strong>  leads to problems when trying to retrieve the <strong>windown.location</strong> object.      (Same does the <strong>encodeURI()</strong> method)<p/>
<p>Only reliable method if you need window.location, seems to be the old      obsolete <strong>document.write()</strong> method.</p>
 <iframe id="iframe1"></iframe>
 <iframe id="iframe2"></iframe>
 <iframe id="iframe3"></iframe>
 <iframe id="iframe4"></iframe>
 </div>

CSS

@import url(https://fonts.googleapis.com /css?family=Fira+Sans:400,500italic);

html {
height: 100%;
background-color: rgba(34,32,36,1);
}
body {
text-align: center;
font: normal 100% 'Fira Sans', sans-serif;
color: #aaa;
}
iframe {
width: 40%;
height: 200px;
background: white;

}

Js

var template = [
'<!DOCTYPE HTML>',
'<html>',
'<head>',
'</head>',
'<body>',
'<script>',
'document.write("<pre>" + JSON.stringify(window.location, null, 4) + 

"</pre>");',
'<\/script>',
'</body>',
'</html>'
].join('');

var iframe1El = document.querySelector('#iframe1');
var iframe1 = iframe1El.contentWindow || ( 
iframe1El.contentDocument.document || iframe1El.contentDocument);

 var iframe2El = document.querySelector('#iframe2');  
 var iframe2 = iframe2El.contentWindow || 
 (  iframe2El.contentDocument.document || iframe2El.contentDocument);

 var iframe3El = document.querySelector('#iframe3');
 var iframe3 = iframe3El.contentWindow || 
 (    iframe3El.contentDocument.document ||     

 iframe3El.contentDocument);

 var iframe4El = document.querySelector('#iframe4');
 var iframe4 = iframe4El.contentWindow || 
 ( iframe4El.contentDocument.document || iframe4El.contentDocument);

 iframe1.document.open();
 iframe1.document.write(template);
 iframe1.document.close();

 var bData = new Blob([template], {type: 'text/html'});
 iframe2El.onload = function() { window.URL.revokeObjectURL(bData); };
 iframe2El.src = window.URL.createObjectURL(bData);

 iframe3El.src = 'data:text/html;charset=utf-8,' +  
 encodeURI(template);

 iframe4El.srcdoc = template;
0
Ahmed Sh

oui, vous pouvez utiliser Iframe avec -Window-Emplacement-Remplacer pour référence, vous pouvez utiliser cette liaison réf. emplacement JavaScript.replace et iframe

0
umang naik

Vous pouvez basculer une classe active sur l'élément parent comme celui-ci à l'aide d'événements de clic d'ancrage.

// Code goes here

$(window).on('load', function() {
  $('.accordion section').on('click', '.ac-open', function(e) {
    e.preventDefault();
    $(e.target).parent().addClass('active');
  });

  $('.accordion section').on('click', '.ac-close', function(e) {
    e.preventDefault();
    $(e.target).parent().removeClass('active');
  });
});
/* Styles go here */

html,
body {
  margin: 0;
  padding: 0;
}

.flt-lft {
  float: left;
  margin: 16px;
}

h4 {
  text-align: center;
  margin: 0;
  padding: 8px;
  color: white;
  background-color: green;
}


/* #sample.example .accordion {
  margin-left: 50px;
  margin-top: 50px;
} */

#sample.example section {
  box-sizing: border-box;
  clear: both;
  position: relative;
  display: block;
  width: 300px;
  height: 32px;
  padding: 0;
  background-color: #fff;
  box-shadow: inset 0 0 1px 1px #000;
  overflow: hidden;
}

#sample.example section.active {
  height: auto;
}

#sample.example a {
  box-sizing: border-box;
  display: block;
  float: right;
  width: 50%;
  height: 32px;
  margin: 0;
  padding: 4px;
  text-align: center;
  font-size: 16px;
  color: #000;
  background-color: #fff;
  box-shadow: inset 0 0 1px 1px #000;
}

#sample.example p {
  box-sizing: border-box;
  clear: both;
  display: block;
  width: 100%;
  padding: 16px;
  margin: 16px 0 0;
  text-align: center;
  color: #000;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <link rel="stylesheet" href="style.css">
</head>

<body>

  <div class="container">

    <div class="flt-lft">
      <h4>parent</h4>
      <div id="sample" class="example">
        <article class="accordion">
          <section id="ac1">
            <a href="index.html#ac0" class="ac-close">Close</a>
            <a href="index.html#ac1" class="ac-open">Open</a>
            <div class="ac-content">
              <p>The elephants talking in their sleep kept me up so late.</p>
            </div>
          </section>
        </article>
      </div>
    </div>

    <div class="flt-lft">
      <h4>iframe</h4>
      <iframe src="child.html"></iframe>
    </div>

  </div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="script.js"></script>
</body>

</html>
0
Yushan Fernando