NAME
    "CGI::TabPane" - Support panes with clickable tabs

Synopsis
            use CGI::TabPane;

            CGI::TabPane -> new(data => [...]) -> get('html');

Description
    "CGI::TabPane" is a pure Perl module.

    It is a wrapper around the superb JavaScript package 'Tab Pane' by Erik
    Arvidsson.

    Erik's article on Tab Pane is here:
    http://webfx.eae.net/dhtml/tabpane/tabpane.html

    I have simplified some of Erik's files, and renamed some, to make
    shipping and installing easier.

Installation
    The makefile will install /perl/site/lib/CGI/TabPane.pm.

    You must manually install <Document Root>/css/tabpane/*.[css|png] and
    <Document Root>/js/tabpane/*.js.

    If you choose to put the CSS elsewhere, you'll need to call
    new(final_css => '/new/path/final.css'). Similarly for style_css.

    Note: If you put webfxlayout.css elsewhere, you'll have to edit
    webfxlayout.js.

    If you choose to put the JavaScript elsewhere, you'll need to call
    new(tabpane_js => '/new/path/tabpane.css'). Similarly for
    webfxlayout_js.

    These options can be used together, and can be passed into "set()"
    rather than "new()".

Distributions
    This module is available both as a Unix-style distro (*.tgz) and an
    ActiveState-style distro (*.ppd). The latter is shipped in a *.zip file.

    See http://savage.net.au/Perl-modules.html for details.

    See http://savage.net.au/Perl-modules/html/installing-a-module.html for
    help on unpacking and installing each type of distro.

Constructor and initialization
    new(...) returns a "CGI::TabPane" object.

    This is the class's contructor.

    Usage: CGI::TabPane -> new().

    This method takes a set of parameters. Only the data parameter is
    mandatory.

    For each parameter you wish to use, call new as new(param_1 => value_1,
    ...).

    data
        This value holds all the information required to build the panes and
        tabs per pane.

        See the sections below called 'Terminology' and 'The Structure of
        the Data' for details.

        The default value is '' (the empty string), which will die because
        you must pass in an array ref.

        This parameter is mandatory.

    final_css
        This value is the name of a CSS file. The module ships with a
        suitable file called final.css.

        Warning: Do not edit final.css. Even tiny changes will have horrible
        effects on the output.

        The default value is '/css/tabpane/final.css'.

        This parameter is optional.

    html
        Normally you would not do this, but if you want, you can pass in a
        value for the "html" parameter, and the HTML generated by this
        module will be appended to your initial value.

        The default value is ''.

        This parameter is optional.

    infix_html
        This value is a string of HTML to be inserted between panes, to
        separate them vertically.

        A typical value might be: '<p>&nbsp;</p><p>&nbsp;</p>'.

        The default value is '' (the empty string).

        This parameter is optional.

    prefix_html
        This value is a string of HTML to be inserted before the first pane.

        A typical value might be: '<p>&nbsp;</p><p>&nbsp;</p>'.

        The default value is '' (the empty string).

        This parameter is optional.

    style_css
        This value is the name of a CSS file which determines the overall
        style of the output. The module ships with three suitable files:

        luna.css
        webfx.css
        winclassic.css

        The default value is '/css/tabpane/luna.css'.

        This parameter is optional.

    suffix_html
        This value is a string of HTML to be inserted after the last pane.

        A typical value might be: '<p>&nbsp;</p><p>&nbsp;</p>'.

        The default value is '' (the empty string).

        This parameter is optional.

    tabpane_js
        This value is the name of a JavaScript file. The module ships with a
        suitable file called tabpane.js.

        Warning: Do not edit tabpane.js. Even tiny changes will have
        horrible effects on the output.

        The default value is '/js/tabpane/tabpane.js'.

        This parameter is optional.

    webfxlayout_js
        This value is the name of a JavaScript file. The module ships with a
        suitable file called webfxlayout.js.

        Warning: Do not edit webfxlayout.js. Even tiny changes will have
        horrible effects on the output.

        The default value is '/js/tabpane/webfxlayout.js'.

        This parameter is optional.

Terminology
    The comments below this diagram define a few terms.

    The example shipped with this module will make things much clearer. See
    the examples/ directory.

    Alternately, go straight to Erik's demo at:
    http://webfx.eae.net/dhtml/tabpane/demo.html

            [Tab 1-1] [Tab 1-2] [TAB 1-3] [Tab 1-4]
            [===============================================]
            [ Text for tab 1-3                              ]
            [===============================================]

            [TAB 2-1] [Tab 2-2]
            [==============================]
            [ +Legend--------------------+ ]
            [ |Text for tab 2-1          | ]
            [ +--------------------------+ ]
            [==============================]

    Pane
        We have 2 'panes', one on top of the other.

        Panes are tiled vertically.

        Use the "infix_html" parameter to "new()" or "set()" to change the
        vertical separation of the panes.

    Tab The top pane has 4 'tabs' side-by-side. The bottom pane has 2 tabs.

        Tabs are tiled horizontally.

    Current tab
        The current tab within a pane is the tab most-recently clicked.

        Tab 3 in the 1st pane and tab 1 in the 2nd pane are in upper case in
        the diagram to indicate they are the 'current tab' in each pane. The
        upper case above is just something I made up for the purposes of
        writing this document. Of course, text is not converted to upper
        case by this module.

                Note: Tabs can be clicked with a mouse, and they can be clicked by executing code.

    Current text
        The text associated with the current tab is called the 'current
        text'.

    Body
        When a tab is clicked it becomes the current tab, and its text
        becomes the current text, and this text is displayed in the 'body'
        of the pane, completely replacing any existing text being displayed
        in the body.

    Legend
        It is possible to use the HTML tag 'legend' to cause a box to be
        drawn by the web client (browser) around the current text.

        Further, it is possible to get the web client to write a string of
        text on top of the upper left part of this box.

        Such a string is called the 'legend'. See above for an example. See
        the examples/ directory for a better example.

The Structure of the Data
    Our first problem is to define a data structure which allows us to
    neatly supply our own data to populate a set of panes and each set of
    tabs per pane.

    Data for a set of panes
        The data structure defining the panes is an array ref. Each element
        of the array provides data for 1 pane.

        So, the above diagram will be something like:

                [<Data for 1st pane>, <Data for 2nd pane>].

    Data for a set of tabs
        The data structure defining the tabs for 1 pane is an array ref.
        Each element of the array provides data for 1 tab.

        So, the above diagram will be something like:

                <Data for 1st pane>:

                [<Data for 1st tab of 1st pane>, <Data for 2nd tab of 1st pane>, ...].

                <Data for 2nd pane>:

                [<Data for 1st tab of 2nd pane>, <Data for 2nd tab of 2nd pane>].

    Data for 1 tab without a legend
        In the absence of a legend, the data for 1 tab is a hash ref:

                <Data for any tab (without a legend) of any pane>:

                {'Text for tab' => 'Text for body of pane'}

        Recall from the discussion of 'body' above: 'Text for body of pane'
        means the text which is to be displayed when this particular tab if
        clicked.

        In the diagram, then, the data for the 3rd tab of the 1st pane is:

                {'Tab 1-3' => 'Text for tab 1-3'}

    Data for 1 tab with a legend
        In the presence of a legend, the data for 1 tab is a hash ref within
        a hash ref:

                <Data for any tab (with a legend) of any pane>:

                {'Text for tab' => {'Text for legend' => 'Text for body of pane'} }

        In the diagram, then, the data for the 1st tab of the 2nd pane is:

                {'Tab 2-1' => {'Legend' => 'Text for tab 2-1'} }

    Data for nested panes and tabs
        In the presence of nested panes, the data for 1 tab is an array ref
        within a hash ref:

                <Data for a nested pane>:

                {'Text for tab' => [<Data for 1st nested tab>, <Data for 2nd nested tab>, ...]}

        Warning: This module will only handle 2 levels in this hierarchy of
        nesting, since it uses hard-coded CSS tokens for the classes of the
        <div>s involved. By '2 levels' I mean 1 outer pane and 1 inner pane.

        Warning: To have one nested pane, with its own set of tabs, makes
        sense. To add more complexity than that surely means your design is
        too complex. By 'more complexity' I mean 2 panes displayed
        vertically within 1 pane. So don't do that.

    Lastly, the entire data structure for the diagram could be:

            [      # All panes
                [  # 1st pane
                    {'Tab 1-1' => 'Text for tab 1-1'},
                    {'Tab 1-2' => 'Text for tab 1-2'},
                    {'Tab 1-3' => 'Text for tab 1-3'},
                    {'Tab 1-4' => 'Text for tab 1-4'},
                ],
                [  # 2nd pane
                    {'Tab 2-1' => {'Legend' => 'Text for tab 2-1'} },
                    {'Tab 2-2' => 'Text for tab 2-2'},
                ],
            ]

    You are strongly urged to examine the demo examples/test-cgi-tabpane.cgi
    to get an understanding of how to construct the required data structure.

Method: get($name_of_thing_to_get)
    Returns a string.

    The 'name of the thing to get' is any of the parameters which can be
    passed in to "new()":

    data
    final_css
    html
        This is the one which you absolutely must call.

    infix_html
    prefix_html
    style_css
    suffix_html
    tabpane_js
    webfxlayout_js

    In each case, the current value of the parameter held within the
    "CGI::TabPane" object is returned.

    See the demo examples/test-cgi-tabpane.cgi for an example.

Example code
    See the examples/ directory in the distro.

Required Modules
    Carp.

Changes
    See Changes.txt.

Related Modules
    CGI::Explorer, also one of my modules, is a pure Perl wrapper around
    another superb package from the House of EAE, this time 'XTree' by Emil
    A Eklund.

    Emil and Erik share the web site http://webfx.eae.net/ - please drop in
    there and express your thanx.

Author
    "CGI::TabPane" was written by Ron Savage *<ron@savage.net.au>* in 2004.

    Home page: http://savage.net.au/index.html

Copyright
    Australian copyright (c) 2004, Ron Savage. All rights reserved.

            All Programs of mine are 'OSI Certified Open Source Software';
            you can redistribute them and/or modify them under the terms of
            The Artistic License, a copy of which is available at:
            http://www.opensource.org/licenses/index.html

