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).
window.location.replace('/samepage.html#onpage_anchor')
dans la console.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:
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:
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.
L'extrait ne se comporte pas comme ça dans un vrai navigateur, le JavaScript ne fonctionne pas.
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.
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:
href
et le dépose dans window.location.replace()
.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?
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;
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
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>