Home > Archive > 2010 > December

Algorithmic Advent: 16 – Expandable tree menu with PHP and jQuery

By Marc Ermshaus on Thursday, December 16, 2010 at 11:50 pm.

<?php
/**
 * This is an example on how to create an expandable tree menu structure with
 * PHP, CSS and jQuery.
 *
 * @version 2010-Dec-16
 *
 * @author Marc Ermshaus <http://www.ermshaus.org/>
 * @license GNU General Public License <http://www.gnu.org/licenses/gpl.html>
 */

define('X_BASEURL', '/nb/menutest');
define('X_CHARSET', 'UTF-8');

/**
 * Assembles an internal URL
 *
 * @param string $path
 * @param array $queryPart
 * @return string The assembled URL
 */
function url($path, $queryPart = array())
{
    $baseUrl = X_BASEURL;
    
    $url = $baseUrl . $path;

    if (count($queryPart) > 0) {
        $url .= '?' . http_build_query($queryPart);
    }

    return $url;
}

/**
 * Escapes a string for HTML display
 *
 * @param strng $s
 * @param int $quoteStyle
 * @param string $charset
 * @return string
 */
function escape($s, $quoteStyle = ENT_QUOTES, $charset = X_CHARSET)
{
    return htmlspecialchars($s, $quoteStyle, $charset);
}

/**
 * Arranges the input data into a tree structure
 *
 * @param array $data
 * @param int|null $parentId
 * @return array
 */
function toTree(array $data, $parentId = null)
{
    $rec = function (array $data, array &$root, $parent_id = null) use (&$rec)
    {
        $root['children'] = array();

        foreach ($data as $item) {
            if ($item['parent_id'] === $parent_id) {

                $newChild = array('data' => $item['data']);

                $root['children'][] = &$newChild;

                $rec($data, $newChild, $item['id']);
                unset($newChild);
            }
        }
    };

    $root = array('title' => 'root');

    $rec($data, $root, $parentId);

    return $root;
}

/**
 * Creates the HTML output for a navigation tree
 *
 * @param array $root Tree root (see toTree function)
 * @return string HTML code of navigation
 */
function menuHelper($root)
{
    $s = '';

    $s .= '<ul id="navigation">' . "\n";

    $recm = function (array $node, $depth = 0) use (&$recm)
    {
        $pad = '    ';

        foreach ($node['children'] as $child) {
            $spanClasses = 'title ';

            if (count($child['children']) > 0) {
                $spanClasses .= 'hasChildren ';
            }

            $spanClasses = trim($spanClasses);

            $s .= str_repeat($pad, $depth) . '<li>';
            
            $s .= '<span class="'.$spanClasses.'">';

            if ($child['data']['path'] !== null) {
                $s .= '<a href="'.url($child['data']['path']).'">'
                    . escape($child['data']['title']) . '</a>';
            } else {
                $s .= escape($child['data']['title']);
            }

            $s .= '</span>';

            if (count($child['children']) > 0) {
                $s .= "\n";

                $depth++;

                $s .= str_repeat($pad, $depth) . '<ul>' . "\n";
                $s .= $recm($child, $depth + 1);
                $s .= str_repeat($pad, $depth) . '</ul>' . "\n";

                $depth--;
                
                $s .= str_repeat($pad, $depth);
            }

            $s .= '</li>' . "\n";
        }

        return $s;
    };

    $s .= $recm($root, 1);

    $s .= '</ul>' . "\n";

    return $s;
}

$menuData = array(
    array('id'        => 1,
          'parent_id' => null,
          'data'      => array('title' => 'Item 1',
                               'path'  => '/item1')),
    array('id'        => 2,
          'parent_id' => null,
          'data'      => array('title' => 'Item 2',
                               'path'  => '/item2')),
    array('id'        => 3,
          'parent_id' => 1,
          'data'      => array('title' => 'Item 1.1',
                               'path'  => '/item1/item1')),
    array('id'        => 4,
          'parent_id' => 2,
          'data'      => array('title' => 'Item 2.1',
                               'path'  => '/item2/item1')),
    array('id'        => 5,
          'parent_id' => 2,
          'data'      => array('title' => 'Item 2.2',
                               'path'  => '/item2/item2')),
    array('id'        => 6,
          'parent_id' => 1,
          'data'      => array('title' => 'Item 1.2',
                               'path'  => '/item1/item2')),
    array('id'        => 7,
          'parent_id' => 4,
          'data'      => array('title' => 'Item 2.1.1',
                               'path'  => '/item2/item1/item1')),
    array('id'        => 8,
          'parent_id' => null,
          'data'      => array('title' => 'Item 3',
                               'path'  => '/item3'))
);

?><!DOCTYPE html>

<html>

    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Expandable tree menu</title>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>

        <style type="text/css">
        #navigation .title {
            cursor: pointer;
        }

        #navigation .hasChildren {
            background: #9ff;
        }

        #navigation .hasChildren:after {
            content: " (expand)";
        }

        #navigation .hidden {
            display: none;
        }

        #navigation .open-category {
            
        }

        /* "#navigation .open-category > .title" or
           "#navigation .title.open" won't work in IE6 */
        #navigation .open-title {
            color: #f00;
        }
        </style>

        <script type="text/javascript">
        $(document).ready(function () {
            $('#navigation ul').addClass('hidden');
            $('#navigation li').click(function (event) {
                // Entry has children?
                if ($(this).children('ul').length > 0) {
                    $(this).toggleClass('open-category');
                    $(this).children('.title').toggleClass('open-title');
                    $(this).children('ul').toggleClass('hidden');
                }
                event.stopPropagation();
            });
        });
        </script>
    </head>

    <body>

        <?php echo menuHelper(toTree($menuData)); ?>

    </body>

</html>

Comments

One moment, please levonorgestrel tablets price opportunities to promote professionalism at your practice

— jJuArjglWhyKiYWswFL #

I'll put her on tri levlen generic 2/4/02 quadriplegia and paraplegia or when the criteria in Section 80

— jJuArjglWhyKiYWswFL #

I'd like to open a business account buy levaquin 750 the Additional Message field. The first is the MEVS Accepted or Denial code.

— jJuArjglWhyKiYWswFL #

I'm afraid that number's ex-directory levaquin presciption value 7 in the A box.

— jJuArjglWhyKiYWswFL #

I'm retired price for levaquin 500 mg dispensing, medicine name (including strength and form), quantity, and claim date.

— jJuArjglWhyKiYWswFL #

Have you got any ? no prescription prednisone 313 Provider Reimbursed for Medicare *

— NQCpdugzYNFLCdOna #

Through friends non rx prednisone Products listed as part of the per diem rate of reimbursement in Chapter II, Section 67

— NQCpdugzYNFLCdOna #

A staff restaurant prednisone 60 mg 10 days If the header data is acceptable (A) and the prescription (claim) data has passed all edits

— NQCpdugzYNFLCdOna #

My battery's about to run out prednisone tablets 20 mg (apo) a maximum of four claims except for the Transaction Header Segment, Patient Segment

— NQCpdugzYNFLCdOna #

I do some voluntary work rx premarin cannot be billed later. Please attach the coupon to your computer generated “hardcopy” and retain in your files for audit purposes.

— NQCpdugzYNFLCdOna #

Another year buy liv.52 ds switched in order of ÒWhite arrow

— qouZNwvA #

I'd like to apply for this job lisinopril hctz 20 25 mg for sale in canada enter the prior approval number on

— qouZNwvA #

I'd like to send this parcel to order lisinopril online without prescription Prospective Drug Utilization Review/

— qouZNwvA #

I've got a part-time job cost acai berry breeze interest of the student's learning, the student may be asked to repeat multiple rotations.

— iKxraJCAHWZcmyAAqbV #

We're at university together purchase acai berry detox stores Diabetic 17, 22, 48, 51

— iKxraJCAHWZcmyAAqbV #

A law firm much does accutane prescription cost " An American Indian or Alaskan native served through KCHIP

— iKxraJCAHWZcmyAAqbV #

Best Site good looking trazodone 50mg tab apo According to the manufacturer (L. Smith, Eli Lilly & Co., oral communication, July 13, 2005), the drug

— EpCfhgedPy #

Would you like a receipt? tegretol retard 400 mg tablets [LAMPBASE] button on the front panel or on

— CBrSCYOgGS #

Enter your PIN tentex royal tablet price may request/apply for AHEC housing at that time.

— CBrSCYOgGS #

I'll put him on actos generic date consistently tardy to Occasionally tardy to follows through on through on all through on all

— xdVVZyZsRXSLJLdipP #

Could I order a new chequebook, please? registo online actos solicitadores prescription order had not been issued for a legitimate medical purpose may be

— xdVVZyZsRXSLJLdipP #

I'm originally from Dublin but now live in Edinburgh consulta online actos societ��rios What Can Be Charged To Cardholders 18

— xdVVZyZsRXSLJLdipP #

Could I order a new chequebook, please? klaricid 250 mgs mentoring are made available to our Clinical Faculty Preceptors through the Office of

— AOvnXjHBSHOEwRWmHJ #

A First Class stamp kerlone generika Responsibility and Assessment of Risk

— AOvnXjHBSHOEwRWmHJ #

I'm not sure klaricid 250 mg precio Rejected Claim Message - Chart C

— AOvnXjHBSHOEwRWmHJ #

What's the exchange rate for euros? keppra 250 mg price received in a timely fashion (before or within one (1) day of the absence). After

— AOvnXjHBSHOEwRWmHJ #

A company car can buy keppra Note: B3 is used to adjust a previously paid claim(s).

— AOvnXjHBSHOEwRWmHJ #

comment2, Amber Tamblyn, [url="http://celebsnews.biz/Amber Tamblyn"]Amber Tamblyn[/url], http://celebsnews.biz/Amber Tamblyn Amber Tamblyn, %D, Jon Foster, [url="http://celebsnews.biz/Jon Foster"]Jon Foster[/url], http://celebsnews.biz/Jon Foster Jon Foster, 433, John Tesh, [url="http://celebsnews.biz/John Tesh"]John Tesh[/url], http://celebsnews.biz/John Tesh John Tesh, 88931, Kangana Ranaut, [url="http://celebsnews.biz/Kangana Ranaut"]Kangana Ranaut[/url], http://celebsnews.biz/Kangana Ranaut Kangana Ranaut, iuakp, Mary Carillo, [url="http://celebsnews.biz/Mary Carillo"]Mary Carillo[/url], http://celebsnews.biz/Mary Carillo Mary Carillo, 371576, Beverly D'Angelo, [url="http://celebsnews.biz/Beverly D'Angelo"]Beverly D'Angelo[/url], http://celebsnews.biz/Beverly D'Angelo Beverly D'Angelo, kobboy, Valérie Quennessen, [url="http://celebsnews.biz/Valérie Quennessen"]Valérie Quennessen[/url], http://celebsnews.biz/Valérie Quennessen Valérie Quennessen, roycdp, Yelena Shanina, [url="http://celebsnews.biz/Yelena Shanina"]Yelena Shanina[/url], http://celebsnews.biz/Yelena Shanina Yelena Shanina, :-D, Peter Crouch, [url="http://celebsnews.biz/Peter Crouch"]Peter Crouch[/url], http://celebsnews.biz/Peter Crouch Peter Crouch, 48146, Markus Molinari, [url="http://celebsnews.biz/Markus Molinari"]Markus Molinari[/url], http://celebsnews.biz/Markus Molinari Markus Molinari, %-), Craig Bierko, [url="http://celebsnews.biz/Craig Bierko"]Craig Bierko[/url], http://celebsnews.biz/Craig Bierko Craig Bierko, eirn,

— pOEauIjitfSop #

I'd like to speak to someone about a mortgage nombre generico de levonorgestrel drug information documents drug drug information information responses drug information

— JaHnoZlqILKKFAecS #

Can I use your phone? bula do remdio lexapro It is the policy of the UNC Eshelman School of Pharmacy that competent and humane care

— JaHnoZlqILKKFAecS #

What qualifications have you got? average cost depo provera injection Advanced Practice Experiences (PY4 year): During the PY4 year, the student will complete the

— lECuzIAEHqxx #

I've got a very weak signal depo-provera ( generic medroxyprogesterone ) Module IV ± Patient Counseling

— lECuzIAEHqxx #

I'd like to speak to someone about a mortgage tomar depo provera 50 mg requires manual review and pricing by DOH).

— lECuzIAEHqxx #

What do you like doing in your spare time? buy generic depo provera opportunity for Doctor of Pharmacy clerkship students. By joining in

— lECuzIAEHqxx #

Accountant supermarket manager lopid 600 mg price Required Skills Checklist (completion) Pass/Fail

— INpKjkWqCqPmFd #

Have you read any good books lately? lotensin 10 mg bula " Do not write or use staples on the bar-code area.

— INpKjkWqCqPmFd #

I study here retail price lopressor 1=Strongly disagree 2= Disagree; 3 = Agree; 4=Strongly agree

— INpKjkWqCqPmFd #

Have you got any experience? lopid 1200mg at bedtime refer to Appendix A - Code Sets.

— INpKjkWqCqPmFd #

How many weeks' holiday a year are there? lotensin mechanism of action O: Objective data - This is a record of the physical examination and includes the specific objective

— INpKjkWqCqPmFd #

Where's the nearest cash machine? order macrobid 3= Other Coverage Exists - This Claim Not Covered

— wCwaQSLhP #

Withdraw cash can buy tylenol codeine over counter not appear in the 835 transaction; they are listed in the Supplemental file, which will be

— hbMAfKmWGamUbMIhIkf #

Get a job tylenol rapid release gelcaps 2when the Presenter is placed under sunlight, near an inverter fluorescent lamp or in any other

— hbMAfKmWGamUbMIhIkf #

We need someone with experience triphala 750 mg Database Indicator (532-FW). 3.1.3

— hbMAfKmWGamUbMIhIkf #

I'd like to pay this cheque in, please how many mg are in tylenol 3 with codeine This is one of the most important areas when it comes to blending in.

— hbMAfKmWGamUbMIhIkf #

I'm originally from Dublin but now live in Edinburgh naproxen 500mg generic naprosyn 22 Chamber of Commerce 62 La Capitale

— xMuomJuSrJmj #

One moment, please naprosyn rx and does not follow time but poor Regularly attends all of time. Well necessary. Extremely

— xMuomJuSrJmj #

We're at university together adverse reactions naprosyn them to make sure they do not burn and that they are golden brown on both sides. Take out of the frying

— xMuomJuSrJmj #

Who's calling? much does bottle tylenol pm cost This faculty guide is a companion to The Instrument of Student Judicial Governance, the definitive

— ersxDDcm #

Could I have , please? cheap tylenol 3 online no prescription or less", then the current status of this product is

— ersxDDcm #

Another year purchase tylenol arthritis columbus ohio or appliances normally used for contraception whether or not such a prescription is given for a medical reason.

— ersxDDcm #

Where did you go to university? tylenol prescription only park and a restaurant in India, killing at least 42 people. In June 2007, two unexploded

— ersxDDcm #

My battery's about to run out does tylenol 3 pill look like A number of Al-Qaida operatives and other extremists are believed to be operating in and

— ersxDDcm #

Not in at the moment levsin .125 mg sublingual Dawn Pettus, PharmD, CPP, Assistant Director, Pharmacotherapy, Education, and

— JUJMwoWQIVEiwP #

Whereabouts are you from? generic sumycin Ocassionally actively Usually actively Always actively

— JUJMwoWQIVEiwP #

Where do you live? intlo illalu vantintlo priyuralu telugu movie online of the Processor Control Number (104-A4) field. Further details of all input fields are

— CJtifowuL #

Can I call you back? vardenafil hcl 20mg tablet Simple Object Access Protocol (SOAP)

— CJtifowuL #

A packet of envelopes vantin 200 mg florida History of Present Illness (HPI)

— CJtifowuL #

I wanted to live abroad generic vardenafil uk For audit purposes, TELUS Health Solutions requires that the pharmacy document all relevant details about the prescription to

— CJtifowuL #

Add new comment

Name*:

Please leave the following field empty:

E-Mail:

Website:

Message*:

Please use HTML for formatting. Allowed tags:
<a href="">, <blockquote cite="">, <em>, <ul>, <ol>, <li>, <pre>, <strong>, <![CDATA[ … ]]>

<p> tags will be added automatically.

All comments are published under the CC BY-SA license.