Estoy usando Knockout.js
para vincular la src
etiqueta iframe (esto será configurable con respecto al usuario).
Ahora, si el usuario ha configurado http://www.google.com (sé que no se cargará en iframe, por eso lo estoy usando para un escenario -ve) y eso debe mostrarse en IFrame. pero arroja error: -
Se negó a mostrar " http://www.google.co.in/ " en un marco porque estableció "X-Frame-Options" en "SAMEORIGIN".
Tengo el siguiente código para Iframe: -
<iframe class="iframe" id="iframe" data-bind="attr: {src: externalAppUrl, height: iframeheight}">
<p>Hi, This website does not supports IFrame</p>
</iframe>
Lo que quiero es, si la URL no se carga. Quiero mostrar un mensaje personalizado . FIDDLE AQUÍ
Ahora, si uso onload y onerror como: -
<iframe id="browse" style="width:100%;height:100%" onload="alert('Done')" onerror="alert('Failed')"></iframe>
Funciona bien cargando w3schools.com pero no con google.com.
En segundo lugar: si lo hago como una función y lo intento como lo hice en mi violín, no funciona.
<iframe id="browse" style="width:100%;height:100%" onload="load" onerror="error"></iframe>
No sé cómo debería ejecutarlo y capturar el error.
Editado: - He visto que desea llamar a una función si el iframe no se carga o carga la pregunta en stackoverflow, pero muestra un error para los sitios que se pueden cargar en iframe.
Además, he examinado el iframe de Stackoverflow en el evento de carga ¡Gracias!
iframe
truco para detectar si el juego está instalado mediante la<iframe src="roblox-player:foo">
detección de un controlador de URI personalizado. Al detectar esteiframe
error, aparece el botón "Descargar". ¿Cómo lo hacen entonces?<iframe>
técnica para iniciar (y esperaba detectar) un controlador URI registrado en el sistema operativo. Es un juego gratuito, puedes instalarlo y comprobarlo por ti mismo. Cuando te unes a un juego a través del navegador, utiliza un truco de iframe para iniciar el juego. Si falla, muestran el botón "descargar". De alguna manera saben si el URI se manejó correctamente o no. Mi suposición inicial fue detectar eliframe
error, pero las respuestas (así como mis pruebas) parecen sugerir que no es posible. ¿Cómo saben cuando falla el iframe?localhost:7845
es bastante suposición. Primero, alcanzará advertencias / errores de contenido mixto (roblox.com usa HTTPS) y luego, necesitaría puertos de conmutación por error en caso de conflictos. La técnica utilizada para iniciar el software esiframe
. Esto se puede observar examinando la fuente de la página. De alguna manera, cuando esto no inicia el software, pueden detectarlo. Esto se puede hacer a través de un método de "teléfono a casa" + tiempo de espera usando el ID del rastreador del navegador. Menciono esto porque estaiframe
detección de fallas es útil para iniciar aplicaciones asociadas, pero solo si se puede detectar la falla.Creo que puede vincular el
load
evento del iframe, el evento se activa cuando el contenido del iframe está completamente cargado.Al mismo tiempo, puede iniciar un setTimeout, si el iFrame está cargado, borre el tiempo de espera o deje que se active el tiempo de espera.
Código:
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); })); });
Demostración: http://jsfiddle.net/IrvinDominin/QXc6P/
Segundo problema
Es porque pierde los parens en la llamada de función en línea; intenta cambiar esto:
<iframe id="browse" style="width:100%;height:100%" onload="load" onerror="error"></iframe>
dentro de esto:
<iframe id="browse" style="width:100%;height:100%" onload="load('Done func');" onerror="error('failed function');"></iframe>
Demostración: http://jsfiddle.net/IrvinDominin/ALBXR/4/
fuente
La carga siempre será un disparador, soluciono este problema, use el bloque try catch. Lanzará una excepción cuando intente obtener el contentDocument.
iframe.onload = function(){ var that = $(this)[0]; try{ that.contentDocument; } catch(err){ //TODO } }
fuente
Esta es una ligera modificación a la respuesta de Edens, que para mí en Chrome no detectó el error. Aunque seguirá recibiendo un error en la consola: "Se negó a mostrar ' https://www.google.ca/ ' en un marco porque configuró 'X-Frame-Options' en 'sameorigin'". Al menos esto captará el mensaje de error y luego podrá solucionarlo.
<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>
fuente
that.contentDocument
y muchos sitios de trabajo seguirán arrojando un errorthat.contentWindow
durante el proceso de carga.Me enfrenté a un problema similar. Lo resolví sin usar el controlador de carga. Estaba trabajando en el proyecto AngularJs, así que usé $ interval y $ timeout. U también puede usar setTimeout y setInterval. Aquí está el código:
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); });
Cada 0.4 segundos sigue revisando el encabezado del documento iFrame. Algo está presente CORS no detuvo la carga ya que el error CORS muestra una página en blanco. Si no hay nada presente después de 5 segundos, hubo algún error (política de Cors), etc. Mostrar mensaje adecuado. Gracias. Espero que resuelva tu problema.
fuente
Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "..." from accessing a cross-origin frame.
- ¿Está seguro de que funciona entre dominios?Tengo el mismo problema, Chrome no puede disparar un error cuando el iframe src carga el error.
pero en mi caso, solo necesito hacer una solicitud http de dominio cruzado, así que uso el script src / onload / onerror en lugar de iframe. está funcionando bien.
fuente
Lo resolví con
window.length
. Pero con esta solución puede tomar el error actual (X-Frame o 404).iframe.onload = event => { const isLoaded = event.target.contentWindow.window.length // 0 or 1 }
MSDN
fuente
Como se explica en la respuesta aceptada, https://stackoverflow.com/a/18665488/4038790 , debe verificar a través de un servidor.
Debido a que no hay una forma confiable de verificar esto en el navegador, le sugiero que cree un punto final de servidor rápido que pueda usar para verificar si alguna URL se puede cargar a través de iframe. Una vez que su servidor esté en funcionamiento, simplemente envíele una solicitud AJAX para verificar cualquier URL proporcionando la URL en la cadena de consulta como
url
(o lo que desee su servidor). Aquí está el código del servidor en 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)
fuente