Nous pouvons utiliser window.location.replace
pour éviter l'historique et pour cibler les ancres sur la page sans rechargement de page, mais pas dans les iframes?
Le problème est une violation CSP (Content Security Policy), dont les états script-src 'unsafe-inline'
doivent être activés. Sauf que je n'ai pas de CSP défini, et même si j'en définis un et que script-src 'unsafe-inline'
je l' autorise, il 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).
- Ciblez l'iframe dans la console et utilisez-la
window.location.replace('/samepage.html#onpage_anchor')
dans la console. - Ça marche. Il cible l'ancre sur la page sans recharger la page et sans historique.
- Mettez le même code en ligne sur les liens d'ancrage et cela fonctionne.
- Utilisez le même code dans un script externe, obtenez l' erreur de violation csp. Cela fonctionne bien sinon dans un iframe.
J'ai essayé de créer un CSP pour autoriser l'action, mais même les politiques de sécurité de contenu les plus permissives possibles ne le permettraient pas.
Edit: j'ai donc rassemblé des exemples sur plunker qui autorise plusieurs fichiers afin que je puisse utiliser des hrefs appropriés qui référencent les pages parent / enfant.
Remarques sur les exemples de plunker:
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.
Je soupçonne que la violation du CSP ne se déclenche pas sur plunker parce que ce dernier présente du contenu au navigateur via une sorte de couche d'abstraction.
La première fois que vous cliquez sur les liens accordéon dans le parent, cela provoque une actualisation. En effet, la façon dont la page se charge initialement 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 référence à child.html
Ce sont de bons exemples pour montrer le code sans nécessiter de modifications pour le faire fonctionner (comme dans la nécessité de changer les hrefs pour les faire fonctionner dans les extraits de stackoverflow, mentionnés ci-dessous). Il est également bon car il montre que le javascript fonctionne comme il se doit. Mais cela ne montre pas le problème réel. Vous devrez toujours le charger dans votre éditeur et l'exécuter sur un serveur local ou un environnement d'hébergement en direct pour voir le vrai problème.
Exemples Plunker
Avec script: Sans histoire
Sans script: Avec histoire
Exemple de code simplifié
Accordéon simple avec une entrée. Suffisant pour reproduire le problème.
Cliquez sur ouvrir / fermer pour développer / réduire l'accordéon, aucun JS n'est requis. Le JS devrait faire exactement la même chose mais sans historique. Fonctionne bien, mais pas dans un iframe.
Notes d'extrait de code:
Vous pouvez exécuter l'extrait de code pour avoir une idée de ce que je décris, mais cela ne démontre pas réellement le problème.
L'extrait ne se comporte pas comme il le ferait dans un vrai navigateur, le javascript ne fonctionne pas.
L'extrait montre le code, mais il doit ê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 façon dont les liens fonctionnent avec le JS (en remplaçant l'URL entière), ils doivent en fait être comme ceci
href="https://stackoverflow.com/thispage.html#ac1"
plutôt quehref="#ac1"
tels qu'ils apparaissent dans l'extrait de code (ne peuvent pas cibler la page HTML réelle dans l'extrait de code). Donc, si vous essayez cela dans votre éditeur (veuillez le faire), n'oubliez pas de modifier les liens vers ce formatthis_document.html#anchor
afin qu'ils soient toujours les mêmes ancres de page, mais le page.html est inclus dans le lien.
Le scénario
$(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' href
attribut et le dépose dans window.location.replace()
.
2. Écoutez les clics sur les ancres 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, aucune violation CSP. Mais l'exécuter à partir d'un 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 plutôt que dans l'iframe (avec des modifications pour sélectionner les liens au sein de 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 ajoutent de l'histoire. Si vous exécutez le code ci-dessus sans le javascript (ou exécutez simplement l'extrait), ouvrez et fermez l'accordéon plusieurs fois et utilisez le bouton de retour, il reviendra à travers les états de fermeture ouverts.
Cela ne me dérangerait pas de l'historique, mais s'il se trouve dans un iframe, lorsque vous quittez la page parent et que vous y revenez, l'historique de l'iframe est rompu. Revenir en arrière ne revient plus à travers les états de l'accordéon, mais continue simplement à recharger l'iframe. Initialement, les ancres ne provoquent pas de rechargements iframe, mais parcourent simplement l'historique de l'état de l'accordéon, qui fonctionne correctement, jusqu'à ce que vous quittiez la page et reveniez. Ensuite, le retour ne passe plus par les états de l'accordéon, mais passe simplement par une pile de recharges iframe identiques. C'est un comportement très hostile aux utilisateurs.
Je n'ai pas besoin d'utiliser location.replace s'il existe une autre méthode qui fonctionnera. J'ai essayé de nombreuses autres approches et j'ai trouvé que les méthodes qui peuvent atteindre le même résultat entraînent généralement la même erreur.
Le but est simplement d' activer les liens d'ancrage sur la page sans rechargement, et sans historique, à l' intérieur d'un iframe.
Le script en ligne fonctionne. Pouvons-nous le faire fonctionner dans un fichier .js externe?
la source
<a href="#ac0" class="ac-close">Close</a>
devrait fonctionner.Réponses:
oui vous pouvez utiliser iframe avec -window-location-replace pour référence, vous pouvez utiliser ce lien ref Javascript location.replace et iframe
la source
vous pouvez utiliser CSS au lieu de la balise iframe html car la balise iframe est supprimée en html
la source