How to put a <script> in the "body" of a frameset document?
Asked Answered
A

3

5

Usually we put our JavaScript <script> tags at the bottom of an HTML document, right before the closing </body> tag, with the benefit that they are executed after all the elements are already available in the DOM and some more things.

However, I'm using a frame document1 which does have a <frameset> instead of a <body> tag. I don't want to put them in the <head> of the document because they wouldn't have immediate access the DOM elements below3. And I don't want to use <iframe>s in a standard body tag either4. I've tried

<head>
  <title>Framesets are interesting</title>
</head>
<frameset cols="50%,50%">
  <frame id="frame-a" src="a.html">
  <frame id="frame-b" src="b.html">
  <script type="text/javascript">
    console.log("hello world!");
    console.log(document.getElementById("frame-a")); // this is what I'm after
  </script>
</frameset>

However, the script was not executed at all, it didn't even show up in the DOM inspector. Sure, a <frameset> may only contain <frame> and <noframes> tags. But, is there really no way to get scripts execute after a <frame> tag?

Just for reference, placing them after </frameset> like it's sometimes done with <body>s doesn't work either.

1: Yes, I know they're deprecated. They were just the natural choice2 for my project, a neat side-by-side view that shows two documents and scrolls them together in a sophisticated manner.
2: …and I never used them before, so I wanted to give it a try.
3: That is what I ended up with, after all an onload handler is trivial. Still the question remains, I'm curious.
4: works fine, but requires intricate CSS styling

Ax answered 17/3, 2016 at 1:17 Comment(8)
@jfriend00: I don't want to add the script to the frame, I want to add it to the frameset document.Ax
I thought a <frameset> was only suppose to include <frame> or <frameset> tags.Legend
@jfriend00: Yes, that appears to be the reason why my attempt did not work. Is there a way around this?Ax
it seems like you already know the answer my friend...Hartal
Can you create a frame of zero size that just contains your script and add that frame as the last frame? If frames know the structure they're in and are on the same domain, they can all reference each other via script. You will still have load timing issues as you will have to wait until all frames are loaded before accessing the DOM in them.Legend
No idea if this will work, but try adding </frame> after each <frame> tag. At least then it is well formed html5 and the parser ( or DOM ) may be able to accept other elements.Talebearer
There is no such thing as "well formed html5" since HTML5 is not XML, and besides, framesets aren't even part of HTML5.Were
@ArifBurhan: It's well formed HTML4. frames are auto-closing tags, like meta, img or br.Ax
W
5

A <script> element can only appear in either a <head> element or <body> element. It cannot appear as a child of a <frameset> element; a <frameset> can only contain <frame> elements, <noframes> elements, or other <frameset> elements. See the Transitional DTD:

<!ELEMENT FRAMESET - - ((FRAMESET|FRAME)+ & NOFRAMES?) -- window subdivision-->

Normally, browsers are happy to insert elements into other elements where they don't belong in complete defiance of what the DTD says since the DTD is just a rulebook, but this doesn't always happen (for example, you can never put any other flow element into an HTMLParagraphElement no matter how hard you try), so if a browser is refusing to place an HTMLScriptElement in an HTMLFrameSetElement, chances are this is why.

Any workarounds will involve placing a <script> element in either the frameset's <head> element, or within one of the frames. (You can also place a <script> element within a <noframes> element since <noframes> has the same content model as <body>, but this won't solve your problem for obvious reasons.)

Were answered 17/3, 2016 at 2:30 Comment(0)
B
2

Similar problem was solved here: Dynamically set frame src using javascript

<head>
  <title>Framesets are interesting</title>
  <script type="text/javascript">
  function LoadPage(){
    console.log("hello world!");
    console.log(document.getElementById("frame-a")); // this is what I'm after
  }
  </script>
</head>
<frameset cols="50%,50%" onload="LoadPage();">    
  <frame id="frame-a" src="a.html">
  <frame id="frame-b" src="b.html">
</frameset>
Baddie answered 17/3, 2016 at 1:33 Comment(0)
X
1

You can put the script by inserting a frame with a data URI:

<head>
  <title>Framesets are interesting</title>
</head>
<frameset cols="50%,50%">
  <frame id="frame-a" src="a.html">
  <frame id="frame-b" src="b.html">
  <frame src="data:text/html,<script type='text/javascript'>with(parent) {
    console.log('hello world!');
    console.log(document.getElementById('frame-a'));
  }</script>">
</frameset>

Of course, you will need to be careful with quotes, and the script will run in another realm. You can use parent or top to access the window of the outer document.

Xerosis answered 22/1, 2017 at 23:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.