views:

2696

answers:

5

I have a web page that uses a frameset.

Due to scripting and object dependencies, I need to load the frames in a specific order.

I have used this example as a template: The JavaScript Source: Navigation: Frames Load Order

This loads an empty page in place of the page I need to load last, then replaces it with the correct page after the first page has loaded.

However: I also need to use the browser Back button. If you run the sample at the above link, let both frames load, then click the Back button, the top frame reverts to the temporary blank page. It is then necessary to click the Back button again to navigate to the page before the frameset.

Is there a way to force frames to load in a specific order without this Back button behavior - or a way to force the Back button to skip the empty page?

This needs to work with Internet Explorer 6 and 7 and preferably with Firefox 3 as well.

A: 

This is a legacy system. The frameset is necessary.

The ideal solution would be one where the frame loading order could be controlled, but without the use of a temporary empty page.

A: 

Build the frames themselves using JavaScript:

<html>
<head>
<script>
function makeFrame(frameName) {
    var newFrame = document.createElement('frame');
    newFrame.id=frameName;
    if(frameName=="B") {
     newFrame.onload=function() {makeFrame("C")};
     newFrame.src = 'http://www.google.com';
    }
    else {
     newFrame.src = 'http://www.yahoo.com';
    }
    document.getElementById('A').appendChild(newFrame);

}
</script>
</head>
<frameset name='A' id='A' rows="80, *" onload="makeFrame('B')"></frameset>
</html>
Diodeus
Great suggestion, but your sample has a couple of flaws: Both frames get the same id, but more importantly, I cannot get it to work in IE7(?)
I have now tried an enormous number of permutations of your suggestion. Works fine in IE7/IE8 (have not tried IE6), but a weird caching problem in Firefox 3 is causing me problems. Would like to clean up the article, but at this time, I am stuck.
To prevent caching, add some random parameter to your SRC:now = new Date()newFrame.src = 'http://www.yahoo.com?now='+now;
Diodeus
Thanks for pointing out the id bug.
Diodeus
A: 

I tried creating the following three files:

top.htm:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
     <title>Top Frame</title>
     <script type="text/javascript">
      function showMessage(message) {
       if(window.console) {
        console.log(message);
       }
      }
     </script>
    </head>
    <body onload="showMessage('Top loaded')">
     <p>This is the top frame!</p>
    </body>
</html>

bottom.htm:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
     <title>Bottom Frame</title>
     <script type="text/javascript">
      function showMessage(message) {
       if(window.console) {
        console.log(message);
       }
      }
     </script>
    </head>
    <body onload="showMessage('Bottom loaded')">
     <p>This is the bottom frame!</p>
    </body>
</html>

and frametest.htm:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"&gt;
<html>
    <head>
     <title>TopBottom</title>
     <script type="text/javascript">
      function showMessage(message) {
       if(window.console) {
        console.log(message);
       }
      }
      function setTopFrameSource() {
       showMessage('setTopFrameSource begin');
       var t = document.getElementById('topframe');
       t.src = 'top.htm';
       showMessage('setTopFrameSource end');
      }
     </script>
    </head>
    <frameset id='TopBottom' rows="*, *" onload = "showMessage('frameset loaded')">
     <frame id="topframe">
     <frame id="bottomframe" src="bottom.htm" onload = "setTopFrameSource()">
    </frameset>
</html>

I deliberately load the frames bottom first, then top, as this is more likely to show if it works.

If I just open the page, either by entering its url (even repeatedly) or by navigating to it from another page in IE or Firefox, everything works fine.

The logging messages appear as expected: - Bottom loaded - setTopFrameSource begin - setTopFrameSource end - Top loaded - frameset loaded

If, however, the page has already loaded and I hit refresh, I get this sequence of messages: - Top loaded - Bottom loaded - setTopFrameSource begin - setTopFrameSource end - frameset loaded

I have tried various meta tags to force the browser not to cache anything, but nothing works.

Is the whole approach flawed or can someone show me the error of my ways?

A: 

Why not use three iframes in the desired order, then resize/move them to the appropriate places?

<iframe id="a1" src="page-to-load-first.htm"></iframe>
<iframe id="a2" src="page-to-load-second.htm"></iframe>
<iframe id="a3" src="page-to-load-third.htm"></iframe>
<script>
function pos(elem,x,y,w,h) {
   if (!elem.style) elem=document.getElementById(elem);
   elem.style.position='absolute';
   elem.style.top = y+'px';
   elem.style.left= x+'px';
   elem.style.width=w+'px';
   elem.style.height=h+'px';
}
window.onload = function() {
    window.onresize=function() {
        var w = window.innerWidth || document.documentElement.clientWidth;
        var h = window.innerHeight || document.documentElement.clientHeight;
        var w3 = w/3;
        var h2 = h/2;
        pos('a1',0,0,w3,h); /* left 1/3rd */
        pos('a2',w3,0,w3+w3,h2);
        pos('a3',w3,h2,w3+w3,h2);
    };
    window.onresize();
};
</script>
geocar
This is a legacy system. The frameset is required. Even if I could use iframes, your sample would not make any difference: The order in which they appear on the page does not guarantee that they will load in that order. Suppose the first iframe loaded in 2 seconds and the second frame in 1 second?
IFrames are regular dom elements (unlike frames), which means document.createElement() can be used to create them. Using window.onresize can be used to emulate the frameset environment.Why do you keep saying "this is a legacy system". Do you mean that you cannot change the initial content?
geocar
Legacy = rest of system expects pages to reside in frames. Changing model means changing code in other places. IFrames might make it easier to control the flow. Have to try it out, but still hoping for a fix to the frames problem as IFrames might not be a viable option for me.
IFrames work a lot like other frames; they exist in window.frames, if they have names (that match the ids) then target="" works like you'd expect.
geocar
A: 

You mention this quite a lot in this post...

This is a legacy system. The frameset is required.

If you are working on a legacy system, then I think it is time you accepted how framesets behave in terms of the browser's back button. If it is truly a legacy system, you don't need to fix this behaviour. If it is actually NOT a legacy system and you need to fix this problem, you need to get away from using a frameset. Framesets were deprecated from the HTML standards and shouldn't be used.

Sohnee