Location: PHPKode > scripts > Simple tabbed menu > simple-tabbed-menu/class.tabMenuBase.php
<?

/**
 * @author Dick Munroe <hide@address.com>
 * @copyright copyright @ 2006 by Dick Munroe, Cottage Software Works, Inc.
 * @license http://www.csworks.com/publications/ModifiedNetBSD.html
 * @version 1.2.3
 * @package Simple Tab Menu
 * @example ./example.php
 *
 * Design and implementation of this class was inspired by the tab menu class of
 * vedanta_dot_barooah_at_gmail_dot_com, available from www.phpclasses.com
 *
 * Edit History:
 *
 *  Dick Munroe (hide@address.com) 25-Apr-2006
 *      Fix link array processing order.
 *      Set widths of array item tables.
 *      Get height of TD containing menu items right.
 *
 *  Dick Munroe (hide@address.com) 26-Apr-2006
 *      Add child menu capability.
 *
 *  Dick Munroe (hide@address.com) 01-May-2006
 *      Add mechanism for adding attributes to the anchors in the menu.
 *      Get rid of empty label td in child menu.  Use CSS for alignment.
 *      Add tag to identify and active parent item.
 *
 *  Dick Munroe (hide@address.com) 03-May-2006
 *      Add documentation as the class is turning out to be much more
 *      popular than anticipated.
 *      Add specific identifiers for parent and child anchors to try
 *      to get around IE problem.
 *
 *  Dick Munroe (hide@address.com) 11-Jun-2006
 *      Changes for PHP 5 compatibility.
 */

/**
 * Base class for the building of simple tabbed interfaces.
 *
 * The goal is to provide unique classes so that anything that can be adjusted
 * using CSS for any given element of the menu may be adjusted.  The CSS styles
 * generated by default are:
 *
 * 1.   div.allMenus
 *      A div that contains all rows of the menu.
 *
 *  2.  div.aMenu
 *      A division that contains a row of a menu.
 *
 *  3.  div.topMost
 *      A div containing the topmost row of a menu.
 *
 *  4.  div.centerMost
 *      A div containing a row of a menu that isn't either the top or the bottom.
 *
 *  5.  div.bottomMost
 *      A div containing the bottom-most row of a menu.  Single row menus are both
 *      top and bottom-most simultaneously.
 *
 *  6.  td.navOn
 *      The style applied to the tab for the current page.
 *
 *  7.  td.navOff
 *      The style applied to tabs for other pages.
 *
 *  8.  td.leftMostLeft/td.leftMostCenter/td.leftMostRight
 *      Each menu item contains 3 TD, the left boundary box, the center navigation,
 *      and the right boundrary box.
 *
 *  9.  td.middleMostLeft/td.middleMostCenter/td.middleMostRight
 *      Each menu item contains 3 TD, the left boundary box, the center navigation,
 *      and the right boundrary box.  This is access to all menu items not left
 *      or right.
 *
 *  10. td.rightMostLeft/td.rightMostCenter/td.rightMostRight
 *      Each menu item contains 3 TD, the left boundary box, the center navigation,
 *      and the right boundrary box.  This is access to the rightMost menu items.
 *      Single element rows will have both left and right items.
 *
 *  11. td.label
 *      If a menu is labelled, this style applies.
 *
 *  12. div.aChildMenu
 *
 *  13. td.aChildItem
 */

DEFINE('tm_ACHILDMENU', 'aChildMenu') ;
DEFINE('tm_ALLMENUS', 'allMenus') ;
DEFINE('tm_AMENU', 'aMenu') ;

if (!function_exists("cloneObject"))
{
    function &cloneObject(&$o)
    {
        
        if (version_compare(PHP_VERSION, '5.0', '<'))
        {
            $xxx = $o ;
        }
        else
        {
            $xxx = clone($o) ;
        }
        
        return $xxx ;
    }
}

/**
 * Height, in pixels, of a row in a menu.  Set it to the same height as whatever
 * graphic is being used on your system for the left and right arcs of the menu
 * items.
 */

DEFINE('tm_HEIGHT', 20) ;

class tabMenuBase
{
    /**
     * @var integer the height of a row in the menu, in pixels.
     * @access private.
     */
    
    var $m_height = tm_HEIGHT ;
    
    /**
     * @var string generated menu when invoked through the object interface.
     * @access private
     */

    var $m_menu ;

    /**
     * @desc object constructor
     * @param integer [OPTIONAL] the height of a row in the menu.
     * @access public
     */

    function tabMenuBase($theHeight = tm_HEIGHT)
    {
        $this->m_menu = '' ;
        $this->m_height = tm_HEIGHT ;
    }

    /**
     * @desc generate a tabbed interface menu.
     * @param array Returned by tabMenuDescription->getMenu()
     * @param integer the active row (0..n-1)
     * @param integer the active cell within the active row (0..n-1)
     * @param string the orientation of the menu (center, left, right)
     * @param integer the distance from the current page to the top of the document root.
     * @return string the generated menu.
     * @access public
     */

    function &generateMenu($theLinkArray, $theLabel = '', $theActiveRow = 0,
                           $theActiveTab = 0,
                           $theMenuAlignment = 'center',
                           $theDistance = 0)
    {
        $theIndent = 1 ;

        $theMenu =
            sprintf('<div class="%s">%s', tabMenuBase::_allMenus(), "\n") .
            tabMenuBase::_generateMenu($theLinkArray,
                                       $theLabel,
                                       $theActiveRow,
                                       $theActiveTab,
                                       $theMenuAlignment,
                                       $theDistance,
                                       $theIndent) .
            '</div>' .
            "\n" ;

        if (isset($this) && is_object($this) && (is_subclass_of($this, 'tabmenubase')))
        {
            $this->m_menu = $theMenu ;
        }

        return $theMenu ;
    }

    /**
     * @desc return the class containing the entire generated menu.
     * @return string
     * @access private
     */

    function &_allMenus()
    {
        $xxx = tm_ALLMENUS ;
        return $xxx ;
    }

    /**
     * @desc generate the entire menu.
     * @param integer $theIndent the number of indents to start with.
     * @param string $theLabel the label applied to this row of the menu.
     * @param integer $theActiveRow the index (0..n-1) of the row containing the active tab.
     * @param integer $theActiveTab the index (0..m-1) of the active tab within the row.
     * @param string [ENUM] $theMenuAlign the alignment on the page of the menu row, 'left', 'center', 'right'
     * @param integer $theDistance the number of levels (0..n) between the current page and the document root.
     * @param integer $theIndent the current indentation level (0..n)
     * @return string
     * @access private
     */

    function &_generateMenu(&$theLinkArray, &$theLabel, &$theActiveRow,
                            &$theActiveTab, &$theMenuAlign, &$theDistance,
                            &$theIndent)
    {
        $theRow = 0 ;
        $theMenu = '' ;
        foreach ($theLinkArray as $v)
        {
            if (count($theLinkArray) == 1)
            {
                $theStyle = 'topMost bottomMost' ;
            }
            else
            {
                switch ($theRow)
                {
                    case 0:
                        $theStyle = 'topMost' ;
                        break ;

                    case count($theLinkArray) - 1:
                        $theStyle = 'bottomMost' ;
                        break ;

                    default:
                        $theStyle = 'centerMost' ;
                }
            }

            $theMenu .= sprintf('%s<div class="%s">%s',
                                tabMenuBase::_indent($theIndent),
                                $theStyle,
                                "\n") ;
            $theIndent++ ;
            $theMenu .=
                tabMenuBase::_generateAMenu($v,
                                            $theLabel,
                                            ($theRow == $theActiveRow ? $theActiveTab : -1),
                                            $theMenuAlign,
                                            $theDistance,
                                            $theIndent) ;
            $theIndent-- ;
            $theMenu .= sprintf('%s</div>%s',
                                tabMenuBase::_indent($theIndent),
                                "\n") ;
            $theRow++ ;
        }

        return $theMenu ;
    }

    /**
     * @desc generate one row of the menu.
     * @return string the html, with indenting, of a row of the menu.
     * @param mixed $theLinkArray @see tabMenuBase::_generateMenu
     * @param string $theLabel @see tabMenuBase::_generateMenu
     * @param integer $theActiveTab @see tabMenuBase::_generateMenu
     * @param string $theMenuAlign @see tabMenuBase::_generateMenu
     * @param integer $theDistance @see tabMenuBase::_generateMenu
     * @param integer $theIndent @see tabMenuBase::_generateMenu
     * @access private
     */

    function &_generateAMenu(&$theLinkArray, $theLabel, $theActiveTab,
                             $theMenuAlign, &$theDistance, &$theIndent)
    {
        $theTab = 0;
        $theMenu = '' ;

        $theMenu .= sprintf('%s<div class="%s">%s',
                            tabMenuBase::_indent($theIndent),
                            tabMenuBase::_aMenu(),
                            "\n") ;
        $theIndent++ ;

        $theMenu .= sprintf('%s<table width="100%%" cellpadding=0 cellspacing=0 class="nav">%s',
                            tabMenuBase::_indent($theIndent),
                            "\n") ;
        $theIndent++ ;

        $theMenu .= sprintf('%s<tr>%s', tabMenuBase::_indent($theIndent), "\n") ;
        $theIndent++ ;

        if (($theLabel != '') && ($theMenuAlign == "left"))
        {
            $theMenu .= sprintf('%s<td class="label" width="100%%" align="left">&nbsp;%s</td>%s',
                                tabMenuBase::_indent($theIndent), $theLabel, "\n") ;
        }

        $theChildMenu = NULL ;

        foreach ($theLinkArray as $k => $v)
        {
            if($theTab == $theActiveTab)
            {
                $menuStyle="navOn";
            }
            else
            {
                $menuStyle="navOff";
            }

            if (count($theLinkArray) == 1)
            {
                $tabStyle = array('leftMost', 'rightMost') ;
            }
            else
            {
                switch ($theTab)
                {
                    case 0:
                        $tabStyle = array("leftMost") ;
                        break ;

                    case count($theLinkArray) - 1:
                        $tabStyle = array("rightMost") ;
                        break ;

                    default:
                        $tabStyle = array("middleMost") ;
                        break ;
                }
            }

            $theMenu .= sprintf('%s<td width="%s" valign="top" height="100%%">%s',
                                tabMenuBase::_indent($theIndent),
                                ($theMenuAlign == 'center' ? tabMenuBase::width(floatval(count($theLinkArray))) : '0%'),
                                "\n") ;
            $theIndent++ ;

            $theMenu .= sprintf('%s<table width="100%%" border="0" cellpadding="0" cellspacing="0" height="100%%">%s',
                                tabMenuBase::_indent($theIndent),
                                "\n") ;
            $theIndent++ ;

            $theMenu .= sprintf('%s<tr>%s', tabMenuBase::_indent($theIndent), "\n") ;
            $theIndent++ ;

            $xxx = (($theTab == $theActiveTab) && ($v[$k][0] !== NULL) ? ' parentMenuItem' : '') ;

            $theMenu .= sprintf('%s<td valign="top" class="%s%s"><img src="%simages/left_arc.gif"></td>%s',
                                tabMenuBase::_indent($theIndent),
                                $menuStyle,
                                tabMenuBase::tabStyle($tabStyle, 'Left') . $xxx,
                                tabMenuBase::distance($theDistance),
                                "\n") ;

            $theMenu .= sprintf('%s<td width="100%%" height="%d"  align="center" valign="middle" class="%s%s">%s',
                                tabMenuBase::_indent($theIndent),
                                tabMenuBase::_height(),
                                $menuStyle,
                                tabMenuBase::tabStyle($tabStyle, 'Center') . $xxx,
                                "\n") ;
            $theIndent++ ;

            if ($theTab == $theActiveTab)
            {
                $theMenu .= sprintf('%s%s%s', tabMenuBase::_indent($theIndent), $k, "\n") ;
                $theChildMenu = $v[$k][0] ;
            }
            else
            {
                if (isset($v[$k][1]) && is_string($v[$k][1]))
                {
                    $theAttributes = ' ' . $v[$k][1] ;
                }
                else if (isset($v[$k][1]) && is_array($v[$k][1]))
                {
                    $theAttributes = ' ' . implode(' ', $v[$k][1]) ;
                }
                else
                {
                    $theAttributes = '' ;
                }
                
                $theMenu .= sprintf('%s<a href="%s" class="parent"%s>%s</a>%s',
                                    tabMenuBase::_indent($theIndent),
                                    $v[0],
                                    $theAttributes,
                                    $k,
                                    "\n") ;
            }

            $theIndent-- ;
            $theMenu .= sprintf('%s</td>%s', tabMenuBase::_indent($theIndent), "\n") ;

            $theMenu .= sprintf('%s<td valign="top" class="%s%s"><img src="%simages/right_arc.gif"></td>%s',
                                tabMenuBase::_indent($theIndent),
                                $menuStyle,
                                tabMenuBase::tabStyle($tabStyle, 'Right') . $xxx,
                                tabMenuBase::distance($theDistance),
                                "\n") ;

            $theIndent-- ;
            $theMenu .= sprintf('%s</tr>%s', tabMenuBase::_indent($theIndent), "\n") ;

            $theIndent-- ;
            $theMenu .= sprintf('%s</table>%s', tabMenuBase::_indent($theIndent), "\n") ;

            $theIndent-- ;
            $theMenu .= sprintf('%s</td>%s', tabMenuBase::_indent($theIndent), "\n") ;

            $theTab++;
        }

        if (($theLabel != '') && ($theMenuAlign=="right"))
        {
            $theMenu .= sprintf('%s<td class="label" width="100%%" align="right">&nbsp;%s</td>%s',
                                tabMenuBase::_indent($theIndent), $theLabel, "\n") ;
        }

        $theIndent-- ;
        $theMenu .= sprintf('%s</tr>%s', tabMenuBase::_indent($theIndent), "\n");

        $theIndent-- ;
        $theMenu .= sprintf('%s</table>%s', tabMenuBase::_indent($theIndent), "\n") ;

        $theIndent-- ;
        $theMenu .= sprintf('%s</div>%s', tabMenuBase::_indent($theIndent), "\n") ;

        if ($theChildMenu !== NULL)
        {
            $theMenu .=
                tabMenuBase::_generateAChildMenu(
                    $theChildMenu,
                    $theMenuAlign,
                    $theDistance,
                    $theIndent) ;
        }

        return $theMenu ;
    }

    /**
     * @desc generate one row of the menu.
     * @return string the html, with indenting, of a row of the menu.
     * @param mixed $theLinkArray @see tabMenuBase::_generateMenu
     * @param string $theMenuAlign @see tabMenuBase::_generateMenu
     * @param integer $theDistance @see tabmenuBase::_generateMenu
     * @param integer $theDistance @see tabMenuBase::_generateMenu
     * @access private
     */

    function &_generateAChildMenu(&$theLinkArray, $theMenuAlign,
                                  &$theDistance, &$theIndent)
    {
        $theMenu = '' ;

        $theMenu .= sprintf('%s<div class="%s">%s',
                            tabMenuBase::_indent($theIndent),
                            tabMenuBase::_aChildMenu(),
                            "\n") ;
        $theIndent++ ;

        $theMenu .= sprintf('%s<table width="100%%" cellpadding=0 cellspacing=0 class="nav">%s',
                            tabMenuBase::_indent($theIndent),
                            "\n") ;
        $theIndent++ ;

        $theMenu .= sprintf('%s<tr height="%d">%s',
                            tabMenuBase::_indent($theIndent),
                            tabMenuBase::_height(),
                            "\n") ;
        $theIndent++ ;

        $theMenu .= sprintf('%s<td class="childItems" valign="center" width="100%%" height="100%%">%s',
                            tabMenuBase::_indent($theIndent),
                            "\n") ;
        $theIndent++ ;

        $theMenu .= tabMenuBase::_indent($theIndent) ;

        $theTab = 0 ;

        foreach ($theLinkArray as $k => $v)
        {
            if (isset($v[$k][1]) && is_string($v[$k][1]))
            {
                $theAttributes = ' ' . $v[$k][1] ;
            }
            else if (isset($v[$k][1]) && is_array($v[$k][1]))
            {
                $theAttributes = ' ' . implode(' ', $v[$k][1]) ;
            }
            else
            {
                $theAttributes = '' ;
            }
            
            $xxx = ($theTab == 0 ? '&nbsp;' : '') ;

            $theMenu .= sprintf('<a href="%s" class="child"%s>%s</a>%s',
                                $v[0],
                                $theAttributes,
                                $xxx . str_replace(' ', '&nbsp;', $k),
                                ($theTab != count($theLinkArray)-1 ? '&nbsp;|&nbsp;' : '')) ;
            $theTab++ ;
        }

        $theMenu .= "\n" ;

        $theIndent-- ;
        $theMenu .= sprintf('%s</td>%s', tabMenuBase::_indent($theIndent), "\n") ;

        $theIndent-- ;
        $theMenu .= sprintf('%s</tr>%s', tabMenuBase::_indent($theIndent), "\n") ;

        $theIndent-- ;
        $theMenu .= sprintf('%s</table>%s', tabMenuBase::_indent($theIndent), "\n") ;

        $theIndent-- ;
        $theMenu .= sprintf('%s</div>%s', tabMenuBase::_indent($theIndent), "\n") ;

        return $theMenu ;
    }

    /**
     * @desc return the class of the division containing a single menu row
     * @return string
     * @access private
     */

    function &_aMenu()
    {
        $xxx = tm_AMENU ;
        return $xxx ;
    }

    /**
     * @desc return the class of the division containing a single menu row
     * @return string
     * @access private
     */

    function &_aChildMenu()
    {
        $xxx = tm_ACHILDMENU ;
        return $xxx ;
    }

    /**
     * @desc generate the indent string.
     * @param integer the number of indents to generate.
     * @return string
     * @access private
     */

    function _indent($theIndent)
    {
        return str_repeat('    ', $theIndent) ;
    }

    /**
     * @desc generate the class name(s) of a single element of a menu.
     * @param array the list of style roots.
     * @param string the style suffix.
     * @return string
     * @access private
     */

    function &tabStyle($theTabStyle, $thePosition)
    {
        $xxx = '' ;

        foreach($theTabStyle as $v)
        {
            $xxx .= ' ' . $v . $thePosition ;
        }

	return $xxx ;
    }

    /**
     * @desc navigate to the document root.
     * @param integer the number of directorys to the document root.
     * @return string
     * @access private
     */

    function distance($theDistance)
    {
        return str_repeat('../', $theDistance) ;
    }

    function width($theNumberOfItems)
    {
        return strval(intval(100.0/$theNumberOfItems)) . '%' ;
    }
    
    function _height()
    {
        if (isset($this) && is_object($this) && (is_subclass_of($this, 'tabmenubase')))
        {
            return $this->m_height ;
        }
        else
        {
            return tm_HEIGHT ;
        }
    }
}
?>
Return current item: Simple tabbed menu