Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Most Respected And High Monks,

I am using HTML::Mason (what a beautiful piece of work that is!) but now I am trying to do something like this:
<Frameset rows="80%,20%"> <Frameset> <Frame src="<% $m->call_next(%args) %>"> </Frameset> <Frameset> <Frame src="footer.html"> </Frameset> </Frameset>
...you get the idea.

I'm sure it can be done, but it isn't completely obvious to me what I need to do... should I make the framesource $m->uri and then concatenate the key/value pairs into the URI string? or is there an easier way?

Advice from those holier and wiser than I would be much appreciated!

with deepest respect,

Mark

Replies are listed 'Best First'.
Re: HTML::Mason and Frames
by jreades (Friar) on Dec 04, 2002 at 14:56 UTC

    Is this some kind of global template that you're working with here? What you're currently doing is forcing the next component in the chain to return a URL, which seems like it probably isn't what you want since the next one in the chain is likely either another autohandler, a dhandler, or a page.

    First off, why use frames at all when you're using Mason? You can simply turn the footer into a component that outputs HTML, and call it from the autohandler like so:

    <html> <head> <title><% $m->base_comp->attr('title') %></title> </head> <body> <% $m->call_next() %> <& /template/footer.comp &> </body> </html>

    Come to think of it, I think it's highly likely you'll get caught in some type of endless recursion unless you configure Mason so that it handles only files of type .mhtml, and then have your next component return links to files of type html which wouldn't be handled by Mason.

      I need frames because I have effectively three panels - one is a query construction panel, a second which lists the immediate results of that query, and a third which displays the details of an element selected from the list of query results. If I dont' have frames, I need to re-issue the query (or somehow store the query results in a hidden field) each time I interact with the page... and the queries are not quick!
Re: HTML::Mason and Frames
by sharkey (Scribe) on Dec 04, 2002 at 18:53 UTC
    jreades is right. You are going to end up in an endless loop if you do it the way to are now. If the frameset page is the autohandler for the main component, the "frame src" tag will cause the browser to fetch the component from the server again which will invoke the same autohandler, and keep embedding frames inside frames ad infinitum.

    So don't try to do framesets (client-side) as a mason autohandler (server-side).

    If you must use framesets, then forget the autohandler for a moment, because the client needs to fetch the frameset separately from any embedded frames. So your referring link will need to point to the frameset, and the "frame src" tags will link the the content pages, which should NOT inherit from the frameset page.

      Gotcha. that's clear. I was slowly starting to realize that this was the direction that I needed to go, but your messages crystallized the fundamental problem in my mind. Thanks very much for pointing me in the right direction! mark
Re: HTML::Mason and Frames
by TGI (Parson) on Dec 05, 2002 at 02:44 UTC

    You are making the same mistake I see so many new web programmers make, you are getting confused about which pieces in the client-server system do what, and when.

    Relax, and take a deep breath and forget what you think you know. Let's look at this situation logically:

    • HTTP is a stateless protocol. Which means that it doesn't remember the last thing you did.
    • The server delivers HTML files (and images) to the client only after the client asks for them.
    • The client wants valid HTML.

    Given the above facts, lets think about what happens when you enter a URL into your browser that points to a frameset containing some text and pictures.

    1. 1. You tell the browser to go to http://example.com/frameset.html
    2. Your browser requests the /frameset.html document from the example.com server.
    3. The server does whatever magic it does and spits out some http headers and some HTML.
    4. Your browser reads the HTML file and presents it to you. In this case you've got a frameset document that looks something like:
      <HTML> <frameset rows=80%,> <frameset> <Frame src="/frame1.html"> </frameset> <frameset> <Frame src="/content/frame2.html"> </frameset> </frameset> </HTML>
      The browser draws the empty frames (or at least prepares to) and then requests the documents specified in the frame tags: /frame1.html and /content/frame2.html.
    5. The server processes each document request and returns headers plus HTML files to the browser.
    6. The browser reads the html files and stuffs them into the appropriate frames for display.

    In your case you are going to be using Mason to the magic URL to HTML transformation on the server side. So let's see what your components will generate: my_file.html

    <HTML> <head><title>My File</title></head> <body><H1>This is my file.</H1></body> </HTML>
    footer.html
    <hr> <p>This is my site. This site is mine. Ehem. I made it and it is mine +, this site that is.</p>
    autohandler
    <HTML> <Frameset rows="80%,20%"> <Frameset> <Frame src="<% $m->call_next(%args) %>"> </Frameset> <Frameset> <Frame src="footer.html"> </Frameset> </Frameset> </HTML>

    If you request my_file.html you will get:

    <HTML> <Frameset rows="80%,20%"> <Frameset> <Frame src="<HTML> <head><title>My File</title></head> <body><H1>This is my file.</H1></body> </HTML>"> </Frameset> <Frameset> <Frame src="footer.html"> </Frameset> </Frameset> </HTML>
    Which will cause your browser to ask for footer.html. footer.html will come back as:
    <HTML> <Frameset rows="80%,20%"> <Frameset> <Frame src="<hr> <p>This is my site. This site is mine. Ehem. I made it and it is mine +, this site that is.</p>"> </Frameset> <Frameset> <Frame src="footer.html"> </Frameset> </Frameset> </HTML>
    Which will in turn request footer.html again and you get an infinite number of broken frames. Not quite what you were looking for, I think.

    Mason is a great way to avoid the need to use frames. Consider this autohandler and example components. Here's how the pieces should be laid out:

    /          <-- This is the mason component root.
    |- html/   <-- This is Apache's document root.
    |  |- autohandler
    |  |- frame.html
    |  \- index.html
    \- cmp/
       \- footer.mas
     
    

    footer.mas can be the exact same as the footer above. I won't repeat that here. Let's look at index.html:

    <h1>My Content</h1> <p>I am content content.</p> <%attr> title => 'Content' </%attr>
    Now for the autohandler:
    <HTML> <head><title>Content</title></head> <body> <% $m->call_next %> <& /cmp/footer.mas &> </table></body> </HTML>

    A request for main.html will get html that looks like:

    <HTML> <head><title><% $m->comp->attr('title') %></title></head> <body> <h1>My Content</h1> <p>I am content content.</p> <hr> <p>This is my site. This site is mine. Ehem. I made it and it is mine +, this sit +e that is.</p></td></tr> </body> </HTML>

    If you must use a frameset, think about it some more, you probably don't. If you still must, then you need to make sure that your autohandler does not perform content wrapping on your frames file. Here's what that looks like:

    <HTML> <Frameset rows="80%,20%"> <Frameset> <Frame src="/somedoc.html"> </Frameset> <Frameset> <Frame src="/somefooter.html"> </Frameset> </Frameset> </HTML> <%flags> interit => undef # Or you could use a special frames autohandler ins +tead of the normal one </%flags>

    Remember that the documents called up by the frames will use mason's content wrapping and will be processed through any autohandlers that might apply.

    Check out the Mason book that just came out. It is quite good. The online docs are also excellent. As a bonus, the folks on the mailing list are quite helpful, too. You can find out about all this stuff at MasonHQ.

    PS, I haven't tested any of this code, I just wrote it off the top of my head, so you'll want to make sure I haven't mixed anything up. For example, I tend to use methods instead of attributes to handle things like the page title in the autohandler, but in this case (read the manual to see why) attribs are more than sufficient, so I may have goofed up the semantics for calling them and the way they behave in respect to inheritance. Read the developers manual, read it six or seven times. I had to before I really got some of the concepts right.


    TGI says moo