NAME CGI::Panel - Create sophisticated event-driven web applications from simple panel objects SYNOPSIS A very simple application... --------------- in simpleapp.cgi: use SimpleApp; my $simple_app = obtain SimpleApp; $simple_app->cycle(); --------------- in SimpleApp.pm: package SimpleApp; use strict; use warnings; use Basket; use base qw(CGI::Panel::MainPanel); sub init { my ($self) = @_; $self->add_panel('basket', new Basket); # Add a sub-panel $self->{count} = 1; # Initialise some persistent data } sub _event_add { # Respond to the button click event below my ($self, $event) = @_; $self->{count}++; # Change the persistent data } sub display { my ($self) = @_; return 'This is a very simple app.
' . # Display the persistent data... "My current count is $self->{count}
" . # Display the sub-panel... $self->panel('basket')->display . '
' . # Display a button that will generate an event... $self->event_button(label => 'Add 1', name => 'add'); } 1; --------------- in Basket.pm: package Basket; use base qw(CGI::Panel); sub display { 'I have the potential to be a shopping basket one day' } 1; --------------- DESCRIPTION CGI::Panel allows applications to be built out of simple object-based components. It'll handle the state of your data and objects so you can write a web application just like a desktop app. You can forget about the http requests and responses, whether we're getting or posting, and all that stuff because that is all handled for you leaving to you interact with a simple API. An application is constructed from a set of 'panels', each of which can contain other panels. The panels are managed behind the scenes as persistent objects. See the sample applications for examples of how complex object-based applications can be built from simple encapsulated components. To try the demo app, copy the contents of the 'demo' directory to a cgi-bin directory. Until the software reaches version 1.00 it will be considered beta software. You should be able to use it in production code, however I strongly recommend that you 'stabilise' your version of the module if you release any code that uses it. By this I mean that, once you've tested your app thorougly, you rename CGI::Panel and CGI::Panel::MainPanel as, for example App::CGIPanel and APP::Panel::CGIMainPanel and inherit from these, then include these with your other panels. This will protect you from any changes in the interface. I'm not planning to make many changes, however one thing I'm considering is making the event objects instead of hashes. USAGE See 'SYNOPSIS' BUGS SUPPORT AUTHOR Robert J. Symes CPAN ID: RSYMES rob@robsymes.com COPYRIGHT Copyright (c) 2002 Robert J. Symes. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of the license can be found in the LICENSE file included with this module. SEE ALSO perl(1). PUBLIC METHODS Each public function/method is described here. These are how you should interact with this module. new Creates a new panel object Use: my $panel = new Panel; init Initialises a panel object. This should be used to add panels to the current panel. We provide a default method here which can be overridden. Example: sub init { my ($self) = @_; $self->add_panel('first_panel', App::Panel::First); $self->add_panel('second_panel', App::Panel::Second); } parent Get or set the parent of the panel object. Examples: my $parent = $self->parent; $self->parent($other_panel); state This method is provided for convenience. Get or set the state. (Simple accessor for $self->{_state}) Examples: my $state = $self->state; $self->state('STATE1'); get_session_id Gets the session id for the application Note: It's essential that all panels are added using the proper add_panel routine for this routine to work correctly. Example: my $id = $self->get_session_id; panel Retrieves a sub-panel by name Example: my $first_panel = $self->panel('first_panel'); get_panels Retrieves the set of panels as a hash Example: my %panels = $self->get_panels; get_id Gets the id of the panel If one is not currently stored, we generate a new one with help from the main panel. This method can be overridden if you want to give a unique name to a panel. Examples: sub get_id { 'unique_name' } or my $id = $self->get_id; and later... $self->get_panel_by_id('unique_name'); or $self->get_panel_by_id($id); See documentation of get_panel_by_id in CGI::Panel::MainPanel for more details. (Of course, you can also just use this get_id to get the auto-generated id and use that later in get_panel_by_id.) main_panel Get the main panel (by recursing up the panel tree) Eventually this will call the routine of the same name in CGI::Panel::MainPanel, which will return the main panel. Example: my $main_panel = $self->main_panel; add_panel Adds a panel to the current panel in a way that maintains referential integrity, ie the child panel's parent value will be set to the current panel. All panels should be added to their parents using this routine to keep referential integrity and allow certain other mechanisms to work. Specify the name to refer to the panel by and the panel object. Example: $self->add_panel('first_panel', new App::Panel::First); remove_panels Remove all the panels from the current panel. Example: $self->remove_panels; local_params Get the parameter list for the current panel. This fetches the parameter list and returns the parameters that are relevant to the current panel. This allows each panel to be written in isolation. Two panels may have input controls (textboxes etc) with the same name and they can each retrieve the value of that input from their %local_params hash. eg my %local_params = $self->local_params my $name = $local_params{name}; event_button Display a button which when pressed re-cycles the application and generates an event to be handled by the next incarnation of the application. The name of the routine that will be called will have _event_ prepended. This is partly for aesthesic reasons but mainly for security, to stop a wily hacker from calling any routine by changing what is passed through the browser. We'll probably be encrypting what is passed through in a later version. Input: label: Caption to display on button name: Name of the event routine: Name of the event routine to call (defaults to name value if not specified) ('_event_' is prepended to the routine name) other_tags: Other tags for the html item eg: $shop->event_button(label => 'Add Item', name => 'add', routine => 'add', other_tags => { class => 'myclass' }); event_link Display a link (which can be an image link) which when pressed re-cycles the application and generates an event to be handled by the next incarnation of the application. Input: label: Caption to display on link * OR * img: Image to display as link name: Name of the event routine: Name of the event routine to call (defaults to name value if not specified) ('_event_' is prepended to the routine name) other_tags: Other tags for the html item img_tags: Other tags for the image (if the link is an image) eg: $shop->event_link(label => 'Add Item', name => 'add', other_tags => { width => 20 }) CGI input functions The CGI input functions are available here with local_ prepended so the name can be made panel-specific, and they can be called as a method. The same effect can be achieved by using the get_localised_name function for the name of the parameter. Example: $self->local_textfield({name => 'testinput', size => 40}) is equivalent to: my $cgi = new CGI; $cgi->textfield({name => $self->get_localised_name('testinput'), size => 40}) Using these methods means that the panel will have exclusive access to the named input parameter. So to obtain the value of the input parameter above, we would write the following: my %local_params = $self->local_params; my $test_input_value = $local_params('testinput'); Note that with this techique, several parameters could have input controls with the same name and they will each receive the correct value. This is especially useful for sets of panels of the same class. get_localised_name Return a name that has the panel id encoded into it. This is used by the local_... functions and can be used to build a custom html input control that will deliver it's value when the panel's local_params method is called. Example: $output .= $cgi->textfield({name => $self->get_localised_name('sometext')}); The equivalent could be done by calling: $output .= $self->local_textfield({name => 'sometext'}); local_textfield Generate a localised textfield Example: $output .= $self->local_textfield({name => 'sometext'});