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

Hi Monks

I'm writing a web demo that communicates with an XMLRPC server for data, so I'm writing it as 2 frames. A top frame for everything the user would normally use and a bottom frame to show the xmlrpc trace. The UI all hinges round these 3 subs.

The problem is that I can only put items into the log frame by using the target on an HTML link or form but I need a form submitted in the main content area to produce output to the main area and also write some logging information to the log area but write_log & write_content only write to the frame they're called from.

I've RTFM'd and experimeted with using -id and/or -name on the frameset definition.

use CGI ':all'; ## Starting Frameset Definition sub makeframeset { # create document frameset. top area for ui # bottom area for XMLRPC trace my $self = self_url; print header, frameset({-border => "1", -rows => "1*,1*", cols => "*"}, frame({-name => 'main', -src => "$self?run=page"}), frame({-name => 'log', -src => "$self?run=log"}) ), end_html; }

I've also experimented with placing (-target => 'log') on start_html or header for each of these:

## Write a message to the log area sub write_log { # write message to the log frame my $messages = \@_; print header, start_html(-target => 'log'), pre(join "\n", @$messages), end_html; }
## Write content to the main page area sub write_content { # write html to the main frame my $html = \@_; print header, start_html(-target => 'main'), join "\n", @$html, end_html; }

And enough content to make it work

my $run = param("run"); if ($run eq 'log') { write_log('Log Message Area'); } elsif ($run eq 'page') { write_content('Main Area'); write_content("<a href='self_url()'>Simulate Run</a>"); } else { write_content("running..."); write_log("foo"); }

just another cpan module author

Replies are listed 'Best First'.
Re: Outputting to 2 HTML frames from 1 CGI
by dorward (Curate) on Oct 10, 2006 at 11:51 UTC

    Over HTTP you make one request, you get one resource back. Getting stuff to generate in multiple frames is not trivial.

    A relatively sane approach might be to make your request to target="_top" and replace the frameset each time. Then store the results you want to display somewhere, and pass an identifier back to the browser in the src attribute of each frame from the generated frameset.

    The browser will then request the two pages passing in the identifer, you can retrieve the actual page or the log based on the request. The data will then be displayed in the frame.

Re: Outputting to 2 HTML frames from 1 CGI
by jasonk (Parson) on Oct 10, 2006 at 12:21 UTC

    I can think of a couple of different approaches, for the non-javascript approach rather than trying to write to two frames at the same time, you can look at it from a different angle, have the log frame simply refresh periodically, and have the write_log method write the logs to a file.

    sub makeframeset { # create document frameset. top area for ui # bottom area for XMLRPC trace my $self = self_url; print header, frameset({-border => "1", -rows => "1*,1*", cols => "*"}, frame({-name => 'main', -src => "$self?run=page"}), frame({-name => 'log', -src => "$self?run=log"}) ), end_html; } sub write_log { open( OUT, ">>/tmp/logfile" ); print OUT "$_<br>" for @_; close( OUT ); } my $run = param("run"); if ($run eq 'log') { print header, '<meta http-equiv="refresh" content="10">'; open( IN, "/tmp/logfile" ); print <IN>; close(IN); } elsif ($run eq 'page') { write_content('Main Area'); write_content("<a href='self_url()'>Simulate Run</a>"); } else { write_content("running..."); write_log("foo"); }

    The alternative would require a little javascript...

    <script language="JavaScript"><!-- function write_log(msg) { parent.log.document.write(msg + '<br>'); } //--></script>

    Then you could do something like this:

    print "This is content area\n"; print "write_content('This is a log message');";

    Note that there are some other problems to overcome with the code you posted (for example, in the elsif($run eq 'page' ) section, you call write_content() twice, but write_content() provides headers and document wrappers, which means you will get two sets of content-type headers, two sets of document tags, etc).


    We're not surrounded, we're in a target-rich environment!