Kita dapat menggunakan window.location.replace
untuk menghindari riwayat, dan menargetkan jangkar pada halaman tanpa memuat ulang halaman, tetapi tidak dalam iframe?
Masalahnya adalah pelanggaran CSP (kebijakan keamanan konten), yang menyatakan script-src 'unsafe-inline'
harus diaktifkan. Kecuali saya tidak memiliki CSP yang ditentukan, dan bahkan jika saya mendefinisikan satu dan mengizinkannya script-src 'unsafe-inline'
masih memberikan kesalahan pelanggaran yang sama. Hasil yang sama di ie11 / chrome / ff.
Iframe di domain yang sama (di direktori yang sama).
- Targetkan iframe di konsol dan gunakan
window.location.replace('/samepage.html#onpage_anchor')
di konsol. - berhasil. Ini menargetkan jangkar pada halaman tanpa memuat ulang halaman, dan tanpa sejarah.
- Letakkan kode yang sama sebaris pada tautan jangkar dan berfungsi.
- Gunakan kode yang sama di skrip eksternal, dapatkan kesalahan pelanggaran csp. Ini berfungsi dengan baik jika tidak di iframe.
Saya mencoba membuat CSP untuk mengizinkan tindakan, tetapi bahkan yang paling permisif kebijakan keamanan konten mungkin akan mengizinkannya.
Sunting: jadi saya mengumpulkan contoh pada plunker yang memungkinkan banyak file sehingga saya bisa menggunakan hrefs yang tepat yang merujuk halaman induk / anak.
Catatan tentang contoh plunker:
Masalahnya tidak direproduksi dalam contoh-contoh ini. Script berfungsi dengan baik, bahkan di iframe. Namun, kode yang sama tidak berfungsi di server lokal saya, atau ketika saya menjalankannya langsung di VPS.
Saya menduga pelanggaran CSP tidak dipicu pada plunker karena plunker menyajikan konten ke browser melalui semacam lapisan abstraksi.
Pertama kali Anda mengklik tautan akordeon di induk, itu menyebabkan penyegaran. Ini karena cara halaman pertama kali memuatnya tidak merujuk index.html. Klik berikutnya berfungsi seperti yang diharapkan tanpa memuat ulang halaman. Bukan masalah di iframe karena ini memang merujuk pada child.html
Ini adalah contoh yang baik untuk menunjukkan kode tanpa memerlukan perubahan untuk membuatnya bekerja (seperti dalam kebutuhan untuk mengubah hrefs agar membuatnya bekerja dalam potongan-potongan stackoverflow, disebutkan di bawah). Ini juga bagus karena menunjukkan javascript berfungsi sebagaimana mestinya. Tapi itu tidak menunjukkan masalah sebenarnya. Anda masih perlu memuatnya di editor Anda dan menjalankannya di server lokal atau lingkungan hosting langsung untuk melihat masalah sebenarnya.
Contoh Plunker
Dengan skrip: Tanpa sejarah
Tanpa skrip: Dengan sejarah
Contoh kode yang disederhanakan
Akordeon sederhana dengan satu entri. Cukup untuk mereproduksi masalah.
Mengklik buka / tutup akan memperluas / menutup akordeon, tidak perlu JS. JS harus melakukan hal yang persis sama tetapi tanpa sejarah. Bekerja dengan baik, tetapi tidak dalam iframe.
Catatan cuplikan kode:
Anda dapat menjalankan cuplikan untuk mendapatkan gagasan tentang apa yang saya uraikan, tetapi sebenarnya tidak menunjukkan masalahnya.
Cuplikan tidak berlaku seperti di browser asli, javascript tidak berfungsi.
Cuplikan memperlihatkan kode, tetapi harus dijalankan dalam iframe untuk melihat masalah. Jalankan di luar iframe untuk melihat perbedaannya dan cara kerjanya.
- Karena cara tautan bekerja dengan JS (mengganti seluruh url), tautan tersebut sebenarnya harus seperti ini
href="https://stackoverflow.com/thispage.html#ac1"
daripada hanyahref="#ac1"
seperti yang ditampilkan di cuplikan (tidak dapat menargetkan laman html aktual di cuplikan). Jadi, jika Anda mencoba ini di editor Anda (silakan lakukan), maka ingatlah untuk mengubah tautan ke format inithis_document.html#anchor
sehingga mereka tetap jangkar halaman yang sama, tetapi page.html termasuk dalam tautan.
Naskah
$(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);
});
Ini sangat sederhana:
1. fungsi acAnch mengambil href
atribut dan memasukkannya ke dalam window.location.replace()
.
2. Dengarkan klik pada jangkar dalam akordeon untuk menjalankan fungsi acAnch.
Jadi semua skrip dijalankan window.location.replace('/this_same_page.html#on_page_anchor')
Jika Anda meletakkannya di konsol berfungsi, tidak ada pelanggaran CSP. Tetapi menjalankannya dari skrip eksternal tidak berfungsi.
Inline pada tautan berfungsi dengan baik:
onclick="event.preventDefault();window.location.replace('/thispage.html#acc0');"
onclick="event.preventDefault();window.location.replace('/thispage.html#acc1');"
Menempatkannya di masing-masing tautan berfungsi dengan baik , tetapi saya benar-benar memilih untuk tidak menggunakan skrip inline seperti itu. Pasti ada cara untuk melakukan ini dengan skrip eksternal.
Saya mencoba menjalankan javascript pada orang tua alih-alih di iframe (dengan modifikasi untuk memilih tautan di dalam anak tentu saja). Hasil kesalahan CSP yang sama.
Mengapa aku melakukan ini?
Nah situs ini jauh lebih kompleks daripada contohnya. Jangkar di iframe berfungsi dengan baik tetapi mereka menambah riwayat.Jika Anda menjalankan kode di atas tanpa javascript, (atau hanya menjalankan snippet), buka dan tutup akordeon beberapa kali, dan gunakan tombol kembali, itu akan kembali melalui status buka tutup.
Saya tidak akan keberatan dengan sejarah, tetapi jika itu ada dalam iframe, ketika Anda meninggalkan halaman induk dan kemudian kembali ke sana, sejarah di iframe rusak. Kembali tidak akan kembali melalui negara akordeon lagi, tetapi sebaliknya hanya memuat ulang iframe. Awalnya jangkar tidak menyebabkan iframe reload tetapi hanya langkah melalui sejarah negara akordeon, yang berfungsi dengan baik, sampai Anda meninggalkan halaman dan kembali. Kemudian kembali tidak lagi melewati negara akordeon, tetapi hanya melewati tumpukan israme identik memuat kembali. Ini adalah perilaku pengguna yang sangat tidak ramah.
Saya tidak perlu menggunakan location.replace jika ada metode lain yang akan berfungsi. Saya telah mencoba banyak pendekatan lain, dan saya telah menemukan bahwa metode yang dapat mencapai hasil yang sama, umumnya menghasilkan kesalahan yang sama.
Tujuannya hanya untuk mengaktifkan tautan jangkar di laman tanpa memuat ulang, dan tanpa riwayat, di dalam iframe.
Skrip inline berfungsi. Bisakah kita membuatnya berfungsi dalam file .js eksternal?
<a href="#ac0" class="ac-close">Close</a>
harus bekerja.