I have this problem on Mozilla (worked perfectly on Chrome) where the nested Iframe doesnt have content after reload (only empty header and body tag)
Somehow you can click on the search bar and enter (instead of reload) to open again and all iFrame will load as intended
---------Working Snippet---------
https://codesandbox.io/s/determined-edison-9rwhwv?file=/index.html
Body index.html
<body>
<div>Index</div>
<iframe id="iframe"></iframe>
<script>
(function () {
var b = document.getElementById("iframe");
b.setAttribute("src", "iframe.html?" + Math.random() * 100);
})();
window.addEventListener('beforeunload', function (event) {
console.log('I am the 1st one.');
});
window.addEventListener('unload', function (event) {
alert('unLoad')
});
</script>
</body>
body iframe.html
<body>
<header>
IFRAME1
</header>
<iframe id="iframe2"></iframe>
<script>
(function () {
var b = document.getElementById("iframe2");
b.setAttribute("src", "iframe2.html?" + Math.random() * 100);
})();
window.addEventListener('beforeunload', function (event) {
console.log('frame 1 before unload.');
});
window.addEventListener('unload', function (event) {
console.log('frame 1 unload.');
});
window.addEventListener('pagehide', (event) => {
if (event.persisted === true) {
console.log('This page *might* be entering the bfcache.');
} else {
console.log('This page will unload normally and be discarded.');
}
});
</script>
</body>
Body iframe2.html
<body>
<header id="h2">
this is iframe 2
</header>
<script src="iframe2.js"></script>
</body>
I read something about bfcache, which is why i tried to put unload event to negate bfcache.
Found this thread with help from zer00ne about mixed content
Mixed Content warning on Chrome due to iframe src
But this seems to be a security issue to do
I got it working by calling the function after load event
window.addEventListener('load', function () {
function setIframe() {
var b = document.getElementById("iframe");
b.setAttribute("src", "iframe.html");
}
setIframe();
})
Hope this helps anyone.
Related
I have a chrome extension that injects javascript code into a webpage like so
if (document.readyState === "complete") {
const html = `
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script type="text/javascript">
console.log(location.href);
function doStuff() {
console.log("do stuff");
}
console.log("onload");
window.onload = function () {
console.log("WINDOW LOADED");
doStuff();
}
</script>
</body>
</html>
`;
document.write(html);
}
However, after I navigate to the page and the extension injects the javascript, I can see in the console that it does log location.href and onload, but the window.onload does not trigger, and I do not see WINDOW LOADED in the console, nor is doStuff() called.
I have also tried using
window.addEventListener('load', (event) => {
console.log('page is fully loaded');
});
as well as
document.addEventListener('DOMContentLoaded', doStuff);
to no avail.
Any help would be appreciated, I have not been able to find anything that works.
I managed to fix this by including at the top of my <script>
setTimeout(() => {
let evt = document.createEvent('Event');
evt.initEvent('load', false, false);
window.dispatchEvent(evt);
}, 300);
And this now causes window.onload to trigger. hope this helps anyone with the same issue
I use onblur and onfocus function in my page.
But also, I use a iframe into page.
And my problem is onblur and andfocus functions not working together into page if I use a iframe.
I clicked in iframe when onblur function is working.But I dont want this function work if I clicked in iframe. I want to run only work it if user will change browser tab
if I will use hasFocus function and users changes browser tab , this time onblur is not working
my js codes:
var after_title = 'Back to page';
var dafault_title = document.title;
var deg;
window.onblur = function () { document.title = after_title; beep(); deg=setTimeout(check,2000); }
window.onfocus = ()=>(deg)?clearTimeout(deg):null;
function beep() {
var snd = new Audio("data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYU=");
snd.play();
}
function check()
{
if(document.hasFocus()){
document.title = dafault_title;
return;
}else{
location.href = './index.php';
}
}
<html>
<head>
<title>Demo Page</title>
</head>
<body>
<br><br><br>default page<br><br><br>
<br><br><br><br>
<iframe id="abc" name="abc" frameborder="1" marginwidth="0" marginheight="0" framespacing="0" width="100px" height="100px">
<p>example include page</p>
</iframe>
</body>
</html>
In order to react to tabchange, don't use the blur and focus events, but rather the Page Visibility API instead:
function handleVisibilityChange() {
if (document.hidden) { // equivalent to "blur"
document.title = after_title; beep(); deg=setTimeout(check,2000);
} else { // equivalent to "focus"
if (deg) {
clearTimeout(deg);
}
}
}
document.addEventListener("visibilitychange", handleVisibilityChange, false);
I have a problem about right click for the iframe. I've done it for the default url of the IFrame but when i displayed any other webpage right click can be usable. I have used those sample codes,
document.onmousedown = disableclick;
status = "Right Click Disabled";
function disableclick(event) {
if (event.button == 2) {
return false;
}
}
function disableContextMenu()
{
document.getElementById("myFrame").contentWindow.document.oncontextmenu = function () { return false; };
}
Here is the iframe
<iframe id="myFrame" name="myFrame" width="1603" height="1064" style="border:none;" src="Iframe.aspx" onload="disableContextMenu();" oncontextmenu="return false"></iframe>
I found the css code "pointer-events:none" but i makes the frame unclickable.
include jquery and then apply this
$( document ).ready(function() {
$('#myFrame').on('contextmenu', function(e) {
e.preventDefault();
});
});
thanks
hope this help
One of my customer has a lot of webistes based on lots of CMS (Wordpress, Drupal and so on). He wanted a generic directory, where professionals can register and share information. It is "generic", as it can be installed on any website (declined according to the website's business).
I developed it inside an iframe, as this can be installed on any CMS, and there were other good reasons to do it this way (CSS, SEO...). But as iframe-browsing is transparent for the navigation bar, I needed to do some tricks to allow visitors to copy/paste professionals's urls, share and fav them. I used history.js to update the navbar's URL, and when direct-accessing the iframe I redirect the user to the right "main website"'s page.
But my problem come when clicking the "back" button. For some reasons, the "statechange" event is not properly fired when clicking "back" a second time.
I developed a demo, you can see my problem live here, and you can download it here.
As you can see on the log div, when you click B and C, you'll get:
Push: /a.html
Push: /b.html
statechange trigered
Push: /c.html
statechange trigered
If you go back once, you'll get:
statechange trigered
Pop: /b.html
And if you go back a second time, you'll get:
Push: /c.html
statechange trigered
Instead of:
statechange trigered
Pop: /a.html
So my question:
What is going on here ?
main.html
<iframe id="my-test" src="a.html" width="500" height="500"></iframe>
<div id="log"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-browser/0.0.6/jquery.browser.min.js"></script>
<script src="history.js/scripts/bundled/html4+html5/jquery.history.js"></script>
<script type="text/javascript">
var test_url = 'http://so.ocarina.fr/test';
// used to avoid listening events trigered by the script itself
var manual_state_change = true;
// used to avoid pushing the previous page
var is_back = false;
$(document).ready(function () {
$('#my-test').load(function () {
// when iframe has loaded, we replace the navbar's url by
// the one from iframe's source.
if (!window.is_back) {
window.manual_state_change = false;
var History = window.History;
if (History.enabled) {
var url = $('#my-test').get(0).contentWindow.location.href;
if (url.indexOf('blank') > 0) {
return;
}
if (url.indexOf('test') > 0) {
url = url.substring(url.indexOf('test') + 4);
if (url.length === 0) {
url = '/';
}
}
$('#log').append('Push: ' + url + '<br/>');
var title = $("#my-test").contents().find("title").html();
document.title = title;
History.pushState({url: decodeURIComponent(url + '')}, title, window.test_url + decodeURIComponent(url + ''));
window.manual_state_change = true;
}
}
window.is_back = false;
}).trigger('load'); // triggered once to replace main.html by a.html
var History = window.History;
if (History.enabled) {
History.Adapter.bind(window, 'statechange', function () {
// if user clicks back, we should change the iframe's location
// to the backward url from history stack.
$('#log').append('statechange trigered <br/>');
if (window.manual_state_change === true) {
window.manual_state_change = false;
var state = History.getState();
var url = state.data.url;
$('#log').append('Pop: ' + url + '<br/>');
window.is_back = true;
$('#my-test').attr('src', window.test_url + url);
$('#my-test')[0].contentWindow.location = window.test_url + url;
window.manual_state_change = true;
}
});
}
});
</script>
a.html
<title>Test A</title>
<script type="text/javascript">
if (top.location === self.location) {
window.location = 'main.html';
}
</script>
<div id="content">
<p>This is test A</p>
Go to test B
</div>
b.html
<title>Test B</title>
<script type="text/javascript">
if (top.location === self.location) {
window.location = 'main.html';
}
</script>
<div id="content">
<p>This is test B</p>
Go to test C
</div>
c.html
<title>Test C</title>
<script type="text/javascript">
if (top.location === self.location) {
window.location = 'main.html';
}
</script>
<div id="content">
<p>This is test C</p>
<p>Go back to A using your backward button...</p>
</div>
I finally found my mistake: when clicking on my iframe's links, browser already add an entry to the history, so I shouldn't add an entry using pushState, but simply replace the current history entry using replaceState.
Bonus: we don't need to handle statechange, browser does anything as naturally as usual. Cool!
See the working demo here.
My code becomes:
<iframe id="my-test" src="a.html" width="500" height="500"></iframe>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-browser/0.0.6/jquery.browser.min.js"></script>
<script src="history.js/scripts/bundled/html4+html5/jquery.history.js"></script>
<script type="text/javascript">
var test_url = 'http://so.ocarina.fr/test2';
$(document).ready(function () {
$('#my-test').load(function () {
// when iframe has loaded, we replace the navbar's url by
// the one from iframe's source.
var History = window.History;
if (History.enabled) {
var url = $('#my-test').get(0).contentWindow.location.href;
if (url.indexOf('blank') > 0) {
return;
}
if (url.indexOf('test') > 0) {
url = url.substring(url.indexOf('test2') + 5);
if (url.length === 0) {
url = '/';
}
}
var title = $("#my-test").contents().find("title").html();
document.title = title;
History.replaceState({}, title, window.test_url + decodeURIComponent(url + '')); // YES!
}
}).trigger('load'); // triggered once to replace main.html by a.html
});
</script>
My goal is to have a parent page change the src of an iframe from blank to its proper url (as to utilize an onload handler in the iframe at a given point, but that's beside the point) and then manipulate the iframe's contents. However, javascript seems oblivious to any elements of an iframe that aren't on its src when the DOM loads. Is there any way around this?
The setTimeouts are intended to allow the DOM and iframe to load.
edit:fixed some stuff.
Here's the containing page:
<html><head>
<script type="text/javascript">
var done = false;
var theIframe;
window.onload = function () {
setTimeout('stuff()', 2000);
clearTimeout('stuff()');
}
function stuff() {
if (!done) {
theIframe = window.myiframe;
theIframe.src = 'http://localhost/TestStuff/redirectIframe.jsp';
done = true;
stuff();
} else {
theIframe.setMe = true;
}
}
</script>
</head>
<body>
<iframe src="" width="500" height="500" id="myiframe" name="myiframe">
</iframe>
</body>
And here's the iframe:
<html>
<head>
<script type="text/javascript">
var setMe = false;
window.onload = setInterval('checker()', 1000);
function checker() {
alert('hi');
if (setMe) {
window.onload = null;
top.location = 'http://www.google.com';
alert('foundit');
} else alert('a');
}
</script>
</head>
<body></body>
</html>
Any ideas?
In this piece of code:
theIframe.src = ...;
stuff();
you're calling stuff() immediately, contrary to what you have described, so in fact you're not allowing any time for the page to load. Maybe you're confused about how setTimeout works: it just schedules a single execution after the specified time, it doesn't automatically delay all calls to a function.
Also, you can use clearTimeout only with a previous ID returned by setTimeout, not with code as you have now.
Try something like this:
window.onload = function() {
loadFrame();
}
function loadFrame() {
theIframe = ...;
theIframe.src = ...;
setTimeout(setSomething, 2000);
}
function setSomething() {
theIframe.setMe = true;
}