Używam Knockout.js
do wiązania src
znacznika iframe (będzie to konfigurowalne w odniesieniu do użytkownika).
Teraz, jeśli użytkownik skonfigurował http://www.google.com (wiem, że nie załaduje się w iframe, dlatego używam go w scenariuszu -ve) i musi to być pokazane w ramce iFrame. ale wyrzuca błąd: -
Odmówił wyświetlenia „ http://www.google.co.in/ ” w ramce, ponieważ ustawił „X-Frame-Options” na „SAMEORIGIN”.
Mam następujący kod dla iframe: -
<iframe class="iframe" id="iframe" data-bind="attr: {src: externalAppUrl, height: iframeheight}">
<p>Hi, This website does not supports IFrame</p>
</iframe>
Chcę, żeby adres URL się nie załadował. Chcę wyświetlić wiadomość niestandardową . FIDDLE TUTAJ
Teraz, jeśli użyję onload i onerror jako: -
<iframe id="browse" style="width:100%;height:100%" onload="alert('Done')" onerror="alert('Failed')"></iframe>
Działa poprawnie, ładując w3schools.com, ale nie z google.com.
Po drugie: - jeśli zrobię to jako funkcja i spróbuję tak, jak robiłem to na moich skrzypcach, to nie działa.
<iframe id="browse" style="width:100%;height:100%" onload="load" onerror="error"></iframe>
Nie wiem, jak mam go uruchomić i wychwycić błąd.
Edytowano: - Widziałem, że chcę wywołać funkcję, jeśli iframe nie ładuje lub nie ładuje pytania w stackoverflow, ale pokazuje błąd dla witryn, które można załadować w iframe.
Przyjrzałem się również elementowi iframe Stackoverflow podczas zdarzenia ładowania. Dzięki!
iframe
sztuczki, aby wykryć, czy gra jest zainstalowana za<iframe src="roblox-player:foo">
pomocą wykrywania niestandardowego modułu obsługi URI. Wykrycie tegoiframe
błędu powoduje wyświetlenie przycisku „Pobierz”. Jak wtedy to robią?<iframe>
technikę do uruchomienia (i miałem nadzieję wykryć) moduł obsługi URI zarejestrowany w systemie operacyjnym. To darmowa gra, możesz ją zainstalować i przekonać się sam. Kiedy dołączasz do gry przez przeglądarkę, używa ona hacka iframe, aby uruchomić grę. Jeśli to się nie powiedzie, pokażą się przycisk „Pobierz”. W jakiś sposób wiedzą, czy identyfikator URI był obsługiwany prawidłowo. Moje wstępne przypuszczenie polegało na wyłapaniuiframe
błędu, ale odpowiedzi (a także moje testy) wydają się sugerować, że nie jest to możliwe. Skąd wiedzą, że iframe zawiedzie?localhost:7845
całkiem założenie. Najpierw trafi na ostrzeżenia / błędy dotyczące mieszanej zawartości (roblox.com używa HTTPS), a następnie będzie potrzebował portów przełączania awaryjnego w przypadku konfliktów. Technika używana do uruchamiania oprogramowania toiframe
. Można to zaobserwować, badając źródło strony. W jakiś sposób, gdy to nie uruchamia oprogramowania, są w stanie to wykryć. Można to zrobić za pomocą metody „telefon do domu” + limit czasu przy użyciu identyfikatora modułu śledzącego w przeglądarce. Wspominam o tym, ponieważ toiframe
wykrywanie awarii jest przydatne do uruchamiania powiązanych aplikacji, ale tylko wtedy, gdy awarię można wykryć.Myślę, że możesz powiązać
load
zdarzenie z iframe, zdarzenie jest uruchamiane, gdy zawartość iframe jest w pełni załadowana.W tym samym czasie możesz uruchomić funkcję setTimeout, jeśli element iFrame jest załadowany, wyczyść limit czasu lub pozwól, aby limit został uruchomiony.
Kod:
var iframeError; function change() { var url = $("#addr").val(); $("#browse").attr("src", url); iframeError = setTimeout(error, 5000); } function load(e) { alert(e); } function error() { alert('error'); } $(document).ready(function () { $('#browse').on('load', (function () { load('ok'); clearTimeout(iframeError); })); });
Demo: http://jsfiddle.net/IrvinDominin/QXc6P/
Drugi problem
Dzieje się tak, ponieważ pomijasz pareny w wywołaniu funkcji wbudowanej; spróbuj to zmienić:
<iframe id="browse" style="width:100%;height:100%" onload="load" onerror="error"></iframe>
zaangażowany w to:
<iframe id="browse" style="width:100%;height:100%" onload="load('Done func');" onerror="error('failed function');"></iframe>
Demo: http://jsfiddle.net/IrvinDominin/ALBXR/4/
źródło
Onload zawsze będzie wyzwalany, rozwiązałem ten problem używając bloku try catch, który wyrzuci wyjątek, gdy spróbujesz pobrać contentDocument.
iframe.onload = function(){ var that = $(this)[0]; try{ that.contentDocument; } catch(err){ //TODO } }
źródło
To drobna modyfikacja odpowiedzi Edensa - która u mnie w chrome nie złapała błędu. Mimo że w konsoli nadal pojawia się błąd: „Odmowa wyświetlenia„ https://www.google.ca/ ”w ramce, ponieważ ustawiono„ X-Frame-Options ”na„ sameorigin ”.” Przynajmniej to złapie komunikat o błędzie i wtedy możesz sobie z tym poradzić.
<iframe id="myframe" src="https://google.ca"></iframe> <script> myframe.onload = function(){ var that = document.getElementById('myframe'); try{ (that.contentWindow||that.contentDocument).location.href; } catch(err){ //err:SecurityError: Blocked a frame with origin "http://*********" from accessing a cross-origin frame. console.log('err:'+err); } } </script>
źródło
that.contentDocument
a wiele działających witryn nadal będzie zgłaszać błądthat.contentWindow
podczas procesu ładowania.Miałem podobny problem. Rozwiązałem to bez użycia modułu obsługującego onload, pracowałem nad projektem AngularJs, więc użyłem $ interwał i $ timeout. Możesz także użyć setTimeout i setInterval. Oto kod:
var stopPolling; var doIframePolling; $scope.showIframe = true; doIframePolling = $interval(function () { if(document.getElementById('UrlIframe') && document.getElementById('UrlIframe').contentDocument.head && document.getElementById('UrlIframe').contentDocument.head.innerHTML != ''){ $interval.cancel(doIframePolling); doIframePolling = undefined; $timeout.cancel(stopPolling); stopPolling = undefined; $scope.showIframe = true; } },400); stopPolling = $timeout(function () { $interval.cancel(doIframePolling); doIframePolling = undefined; $timeout.cancel(stopPolling); stopPolling = undefined; $scope.showIframe = false; },5000); $scope.$on("$destroy",function() { $timeout.cancel(stopPolling); $interval.cancel(doIframePolling); });
Co 0,4 sekundy sprawdzaj nagłówek dokumentu iFrame. Coś jest obecne Ładowanie nie zostało zatrzymane przez CORS, ponieważ błąd CORS pokazuje pustą stronę. Jeśli nic nie jest obecne po 5 sekundach, wystąpił błąd (polityka Cors) itp. Pokaż odpowiednią wiadomość. Dzięki. Mam nadzieję, że to rozwiązuje twój problem.
źródło
Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "..." from accessing a cross-origin frame.
- czy na pewno działa w wielu domenach?Mam ten sam problem, Chrome nie może odpalić przy błędzie w przypadku błędu ładowania iframe src.
ale w moim przypadku potrzebuję tylko żądania HTTP między domenami, więc używam skryptu src / onload / onerror zamiast iframe. działa dobrze.
źródło
Rozwiązałem to z
window.length
. Ale dzięki temu rozwiązaniu możesz wziąć bieżący błąd (X-Frame lub 404).iframe.onload = event => { const isLoaded = event.target.contentWindow.window.length // 0 or 1 }
MSDN
źródło
Jak wyjaśniono w zaakceptowanej odpowiedzi, https://stackoverflow.com/a/18665488/4038790 , musisz sprawdzić za pośrednictwem serwera.
Ponieważ nie ma niezawodnego sposobu sprawdzenia tego w przeglądarce, proponuję zbudować sobie szybki punkt końcowy serwera, którego możesz użyć do sprawdzenia, czy jakikolwiek adres URL jest możliwy do załadowania przez iframe. Gdy serwer jest już uruchomiony, po prostu wyślij do niego żądanie AJAX, aby sprawdzić dowolny adres URL, podając adres URL w ciągu zapytania jako
url
(lub cokolwiek sobie życzy serwer). Oto kod serwera w NodeJs:const express = require('express') const app = express() app.get('/checkCanLoadIframeUrl', (req, res) => { const request = require('request') const Q = require('q') return Q.Promise((resolve) => { const url = decodeURIComponent(req.query.url) const deafultTimeout = setTimeout(() => { // Default to false if no response after 10 seconds resolve(false) }, 10000) request({ url, jar: true /** Maintain cookies through redirects */ }) .on('response', (remoteRes) => { const opts = (remoteRes.headers['x-frame-options'] || '').toLowerCase() resolve(!opts || (opts !== 'deny' && opts !== 'sameorigin')) clearTimeout(deafultTimeout) }) .on('error', function() { resolve(false) clearTimeout(deafultTimeout) }) }).then((result) => { return res.status(200).json(!!result) }) }) app.listen(process.env.PORT || 3100)
źródło