Recently I have been asked for help with a set of HTML pages, that failed to work as expected. The setup consisted of a frameset, where links shown in some frame should open in some other frame. This should be accomplished by the target attribute on the anchor element, or a base element with a target attribute in the page containing the link.
The problem was that links did not open in the desired target frame, but in a different tab.
After some analysis, I found out that this behavior was caused by the presence of a Javascript variable "name", which was present on the page that was initially loaded in the target frame. If the value of that variable did not match the name of the target frame, the link opened on a new tab. In case it matched the target frame name, the link opened in the target frame, as expected.
This happens consistently in recent versions of at least three browsers (tried Firefox, Chrome, and Edge).
I would like to know why it works this way.
Here is a small reproduction of the issue (also available here), with a frameset, three frames with initial content, and two links. The first link, with target="two", opens in frame "two". But the second link, with target="three", does not open in frame "three", instead it opens in a new tab. Apparently this depends on the value of Javascript variable "name" in the initial content of that frame, three.html. But why?
index.html:
<html>
<frameset rows="33%,33%,*">
<frame name="one" src="one.html">
<frame name="two" src="two.html">
<frame name="three" src="three.html">
</frameset>
</html>
one.html:
<html>
<body>
frame "one"
<br>
<a target="two" href="content.html">show content (target="two")</a>
<br>
<a target="three" href="content.html">show content (target="three")</a>
</body>
</html>
two.html:
<html>
<body>
frame "two"
<script>
<!--
var name = "two";
//-->
</script>
</body>
</html>
three.html:
<html>
<body>
frame "three"
<script>
<!--
var name = "two";
//-->
</script>
</body>
</html>
content.html:
<html>
<body>
content
</body>
</html>
The reason for this is that by setting the variable name in the pages, you are overriding the Window.name variable.
And that Window.name variable is what the system uses to determine the Frame's name. When you override this value and change it, and then try to reach the frame with the older value, then you are redirected to a new tab.
HTML file when targeted with link name specified in the frame tag does not open in that named frame. The problem is the frame where it is loaded is calling the other frame to load a new html file does not recognise the name or it can't find where the named frame as specified in the frameset orderly as per syntax. There is no mistake in naming the calling frame. The link opens in itself in its own frame where the html document is calling. It means it opens in the same window frame as _SELF is being executed. The calling frame with its HTML file and primararily the code the anchor tag can't see the window frame I am calling to load the desired HTML file and can't recognise the name I have given to the calling frame.
How to solve.....the first para problem. ?
I reiterate there is nothing wrong in the browser. I have the best app browser line-ups. All execute work fine with all web pages.
Ross
Related
This may be a bit of an x y problem, so I'll give a small bit of background to start with. I am attempting to make a simple dashboard which loads a number of different sites and which cycles between them. To do this I have set up a simple local server along with a html page which gets populated with the different sites in distict frames and then cycles between them by hiding/showing each one in turn. In simple terms, the page looks like this:
<html>
<head></head>
<body>
<iframe id="frame1" src="www.example1.com"> </iframe>
<iframe id="frame2" src="www.example2.com"> </iframe>
<iframe id="frame3" src="www.example2.com"> </iframe>
</body>
</html>
Now, what I would like to do is be able to force a reload of each frame so that the data is up to date. For most sites I can do this with:
document.getElementById['iframe.src'] = document.getElementById['iframe.src']
However, for sites where content changes aren't reflected in the URL, this won't work and will instead 'refresh' the page back to the home page. What I want to do is esentially submit an F5 sort of refresh direct to the frame or use:
document.getElementById("iframe_id").contentWindow.location.href
or
document.getElementById('YOUR IFRAME').contentDocument.location.reload(true);
But, due to CORS, I can't do this. Considering the sites are external sites that I am viewing and have no control over I'm struggling to come up with a way to get around this issue. Is there something pretty obvious that I am missing?
You're not missing anything, that's how the web works. You have no control over a page from another domain, except if you use postMessage() but thas implies the target page acknowledges your messages and reacts accordingly.
In other terms, you won't achieve this unless you have control over the pages you are embedding.
Rather than try and tell the page in the iframe to reload, which you will be blocked from doing. You could instead update the URL in the iframe tag, by adding some random crap to the end of the URL
So for example news.bbc.co.uk would become news.bbc.co.uk?qaz=1, then change this each time you want it to refresh.
You can achieve something like time by removing iframe element & creating again at same place,
this will seems like same page is being refreshed.
working example : this will refresh the frame every 5 second.
<html>
<head></head>
<body>
<div id="frameContainer1">
<iframe id="frame1" width="500" height="500" src="http://www.example.com"> </iframe>
</div>
<script type="text/javascript">
window.onload = function() {
setInterval(function(){
let elem = document.getElementById('frameContainer1');
var elemFrame = document.getElementById('frame1');
elem.removeChild(elemFrame);
var newFrame = document.createElement('iframe');
newFrame.id = 'frame1';
newFrame.setAttribute('src', 'http://www.example.com');
newFrame.width = 500;
newFrame.height = 500;
elem.appendChild(newFrame);
},5000)
}
</script>
</body>
</html>
I have this page
<html>
<body>
<script>
document.domain = "yandex.ru";
</script>
video
</body>
</html>
Sadly, still have link in HTML like /video, instead of yandex.ru/video.
P.S.: links are relative type and don't depends from myself. In certain cases (not all though) - they are incorparated in iframes.
I've been struggling with this one for a few hours now.
I am trying to attach click listeners to elements within an iframe with no src attribute. The entire page is basically inside that bad boy.
When I use "inspect element", the body of iframe looks empty (dunno if that has to do with the fact it has no src attribute.
<iframe id="CoverIframe" name="CoverIframe">
#document
<html>
<head></head>
<body></body>
</html>
</iframe>
When I enter the ID of the iframe in the console, it simply returns null, which prevents me from checking the elements it contains via contents().find() or anything else for that matter. I can only see its content (and by extension the elements on the page) by showing the source code (right click>see source).
Any thoughts on this? Is it because of the absence of src attribute? Any way I can get around it?
Thanks,
Alexis
As you noticed, you can't just set the innerDocument of an iframe like that.
However, you can use its (html-5 only)srcDoc attribute to set it,
<iframe id="CoverIframe" name="CoverIframe" srcdoc="
<html>
<head></head>
<body>hello</body>
</html>"
></iframe>
or use a data:text/html;charset=utf-8,<html><head></head><body>hello</body></html>".
<iframe id="CoverIframe" name="CoverIframe" src="data:text/html;charset=utf-8,<html>
<head></head>
<body>hello</body>
</html>"
></iframe>
But for the later, you will soon need to encodeURI() your page.
So the best is probably using javascript :
<script>
var yourHTML = "<html><head></head><body>hello</body></html>";
function loadFrame(e){e.contentDocument.write(yourHTML)};
</script>
<iframe id="CoverIframe" name="CoverIframe" onload="loadFrame(this)">
► Show code fiddle
Change iframe's window's parent
Is it possible to change the contentWindow.parent of an iframe. What I want to do is:
window.document.getElementById('myframe').contentWindow.parent = window.document.getElementById('myframe').contentWindow.window
The above works in Firefox, Chrome, Opera but not IE.
The reason for doing this my iframe (let's call it TOP) itself has iframes in it (let's call them SUBWINDOWS), and both of them have Javascript that calls "parent.document.getElementById" and such. When you are in a top level window then parent.document.getElementId is the same as document.getElementById because for a top level window parent == window. For the iframe SUBWINDOWS parent.document refers to the the document of the top level window. Seems a bit sloppy, but it works, relying on the fact that parent == window for a top level window.
But now that top level window TOP is now an iframe in a bigger page (let's call it BIG). The Javascript in TOP that does parent.document.getElementById is now referring to BIG's document, whereas before it was referring to TOP's document.
So one quick and easy fix is to change the iframe's parent to point to itself. And this indeed works for Firefox, Chrome, Opera.
Any ideas for how to get it to work for IE?
--
My test code is:
test.html:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<p>Text outside iframe</p>
<iframe id="myframe" src="test_more.html"></iframe>
</body>
</html>
test_more.html:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<p>Text inside iframe</p>
<input type="button" value="window/parent" onclick="alert('window.location.href = ' + window.location.href + '\nparent.location.href = ' + parent.location.href);"/>
</body>
</html>
Put these files on a web server to avoid the same origin policy error and go to the URL like localhost:6144/test/test.html.
I have two level parent-child iframe hierarchy in my HTML pages. I want to get an object of parent window document in its child document for some manipulation. I works majorly with Google Chrome.
parent.document gives 'undefined' in Google Chrome, while in Mozilla it works fine. What's the catch?
For reference, please find below the content of the three files demonstrating the issue,
First file: 'one.html'
<html>
<head>
</head>
<body>
<input type="hidden" id="one_1" name="one_1" />
<iframe id="one" name="one" src="two.html">
</body>
</html>
Second file: 'two.html'
<html>
<head>
</head>
<body>
<input type="hidden" id="two_1" name="two_1" />
<iframe id="two" name="two" src="three.html">
</body>
</html>
Third file: 'three.html'
<html>
<head>
<script type="text/javascript">
function callme() {
alert(parent.document)
alert(top.document)
}
</script>
</head>
<body>
<input type="hidden" id="three_1" name="three_1" />
<button id="click" name="click" onclick="return callme()">Click Me</button>
</body>
</html>
Assuming that 'one.html' is opened with Google Chrome, when I click on the 'Click Me' button, two successive alert boxes appears with 'undefined' value. When I open 'one.html' in Mozilla, it gives two 'objectHTMLDocument' valued alert boxes appears.
Please find below the console messages while clicking on 'Click Me' button,
Unsafe JavaScript attempt to access frame with URL file:///C:/Users/user/Desktop/two.html from frame with URL file:///C:/Users/user/Desktop/three.html. Domains, protocols and ports must match.
three.html:6
callme three.html:6
onclick three.html:13
Unsafe JavaScript attempt to access frame with URL file:///C:/Users/user/Desktop/one.html from frame with URL file:///C:/Users/user/Desktop/three.html. Domains, protocols and ports must match.
three.html:7
callme three.html:7
onclick three.html:13
Thanks in advance.
I would inject from top-down as opposed to accessing bottom-up. I would set a variable in an iFrame by selecting it and storing it into a variable like so:
var frame = document.getElementById('one');
And then inject a reference to the parent:
frame.contentWindow.frame_parent_reference = window;
And then perform this in the next child iFrame replacing "one" with "two". That way, by third.html, we don't ask for parent or top, but can do the following:
alert(frame_parent_reference.document);
alert(frame_parent_reference.frame_parent_reference.document);
Perhaps not super elegant but it definitely gives you a lot of control (and you can check if the custom reference exists for security).
Good luck!