
I origianally developed this module because I thought I was having problems with PHPLayers. It turns out PHPLayers was working fine, but it is still nice to have a good alternative to PHPLayers.
I have structured the module directory as follows
Code: Select all
/modules/JSCookMenu/JSCookMenu.module.php
/modules/JSCookMenu/JSCookMenu/JSCookMenu.js
/modules/JSCookMenu/JSCookMenu/themes (Place themes here)
/modules/JSCookMenu/JSCookMenu/themes/ThemeIE (A example theme director)
Code: Select all
<?php
#########################################################
#
# Module for JSCookMenu (www.cs.ucla.edu/~heng/JSCookMenu/)
#
# Author: Benjamin Carnes (bjcarnes at gmail dot com)
#
# License: Do whatever you want with this. Just don't violate
# the CMS Made Simple licences and leave my name in the credits.
#
# See http://forum.cmsmadesimple.org/index.php?topic=51
# for some good intro info on module development
#
# TODO: Implement theme parameter
# TODO: Support admin link in menu
#
#########################################################
class JSCookMenu extends CMSModule
{
function GetName()
{
return 'JSCookMenu';
}
function GetVersion()
{
return '.02';
}
function GetHelp($lang = 'en_US')
{
return "
<h3>What does this do?</h3>
<p>Prints a dhtml vertical or horizontal menu using the <a href=\"http://www.cs.ucla.edu/~heng/JSCookMenu/\">JSCookMenu (v1.31)</a>.</p>
<h3>How do I use it?</h3>
<p>Just insert the module into your template/page like: <code>{cms_module module='JSCookMenu'}</code></p>
<h3>What parameters does it take?</h3>
<p>
<ul>
<li><em>(optional)</em> <tt>theme</tt> - (ThemeIE, ThemeMiniBlack, ThemeOffice, ThemePanel), Theme for menu. Additional themes
may be added simply by creating a new one and placing it in the modules/JSCookMenu/JSCookMenu/themes/ directory. Default is ThemeIE.
THIS PARAMETER DOESN'T WORK YET.</li>
<li><em>(optional)</em> <tt>showadmin</tt> - 1/0, whether you want to show or not the admin link. Default is 0.</li>
<li><em>(optional)</em> <tt>start_element</tt> - the hierarchy of your element (ie : 1.2 or 3.5.1 for example). This parameter sets the root of the menu.</li>
<li><em>(optional)</em> <tt>number_of_levels</tt> - an integer, the number of levels you want to show in your menu.</li>
<li><em>(optional)</em> <tt>horizontal</tt> - 1/0, whether you want to have a horizontal menu instead of vertical. Default is 1 (horizontal).</li>
</ul>
</p>
";
}
function GetAuthor()
{
return 'Benjamin Carnes';
}
function GetAuthorEmail()
{
return 'bjcarnes at gmail dot com';
}
function GetChangeLog()
{
return "Introducing beta<br /><b>TODO:</b> Implement theme parameter<br /><b>TODO:</b> Support admin link in menu";
}
function IsPluginModule()
{
return true;
}
function ContentPreRender(&$content)
{
$config = $this->cms->config;
$text .= '<__script__ language="JavaScript" SRC="'.$config['root_url'].'/modules/JSCookMenu/JSCookMenu/JSCookMenu.js"></__script>
<__script__ language="JavaScript" SRC="'.$config['root_url'].'/modules/JSCookMenu/JSCookMenu/themes/ThemeIE/theme.js"></__script>';
$content = ereg_replace("<\/head>", $text."</head>", $content);
}
function ContentStylesheet(&$stylesheet)
{
$config = $this->cms->config;
@ob_start();
@readfile(dirname(__FILE__).'/JSCookMenu/themes/ThemeIE/theme.css');
$stylesheet = @ob_get_contents() . $stylesheet;
@ob_end_clean();
}
function DoAction($name, $id, $params)
{
$config = $this->cms->config;
if ($name == 'default')
{
$basedepth = 1;
$allcontent = ContentManager::GetAllContent(false);
# getting menu parameters
$showadmin = isset($params['showadmin']) ? $params['showadmin'] : 0 ;
$horizontal = isset($params['horizontal']) ? $params['horizontal'] : 0 ;
$menu = '';
#Reset the base depth if necessary...
if (isset($params['start_element']))
{
$basedepth = count(split('\.', (string)$params['start_element']));
}
$disabled = array();
$filteredcontent = array();
#Filter out content elements that are disabled or at the wrong level
foreach ($allcontent as $onecontent)
{
#Handy little trick to figure out how deep in the tree we are
#Remember, content comes to use in order of how it should be displayed in the tree already
$depth = count(split('\.', $onecontent->Hierarchy()));
#If hierarchy starts with the start_element (if it's set), then continue on
if (isset($params['start_element']))
{
if ((strpos($onecontent->Hierarchy(), (string)$params['start_element']) === FALSE) || (strpos($onecontent->Hierarchy(), (string)$params['start_element']) != 0))
{
continue;
}
}
#Now check to make sure we're not too many levels deep if number_of_levels is set
if (isset($params['number_of_levels']))
{
$number_of_levels = $params['number_of_levels'] - 1;
$base_level = 1;
#Is start_element set? If so, reset the base_level to it's level
if (isset($params['start_element']))
{
$base_level = count(split('\.', (string)$params['start_element']));
}
#If this element's level is more than base_level + number_of_levels, then scratch it
if ($base_level + $number_of_levels < $depth)
{
continue;
}
}
# Check for inactive items or items set not to show in the menu
if (!$onecontent->Active() || !$onecontent->ShowInMenu())
{
# Stuff the hierarchy position into that array, so we can test for
# children that shouldn't be showing. Put the dot on the end
# since it will only affect children anyway... saves from a
# .1 matching .11
array_push($disabled, $onecontent->Hierarchy() . ".");
continue;
}
$disableme = false;
# Loop through disabled array to see if this is a child that
# shouldn't be showing -- we check this by seeing if the current
# hierarhcy postition starts with one of the disabled positions
foreach ($disabled as $onepos)
{
# Why php doesn't have a starts_with function is beyond me...
if (strstr($onecontent->Hierarchy(), $onepos) == $onecontent->Hierarchy())
{
$disableme = true;
continue; # Break from THIS foreach
}
}
if ($disableme)
{
continue; # Break from main foreach
}
array_push($filteredcontent, $onecontent);
}
/*reset($filteredcontent);
foreach ($filteredcontent as $onecontent)
{
$menu .= $onecontent->Hierarchy()."\n";
}*/
# foreach ($filteredcontent as $onecontent)
# {
# $menu .= $onecontent->MenuText()."<br />";
# }
if (isset($params['horizontal']))
{
$this->WriteMenuJS($menu, $filteredcontent, $params['horizontal']);
}
else
{
$this->WriteMenuJS($menu, $filteredcontent, 1);
}
# if ($showadmin == 1)
# {
# $menu .= ".|---\n";
# $menu .= ".|Admin|".$config['admin_dir']."/\n";
# }
return $menu;
}
//Catch-all
return '';
}
function WriteMenuJS(&$menu, &$filteredcontent, $horizontal)
{
$config = $this->cms->config;
$menu .= "\n<div id=\"jscookmenuid\"></div>\n";
$menu .= "\n<script language=\"JavaScript\"><!--\n";
$menu .= "\nvar jscMenuArr = [";
reset($filteredcontent);
$this->WriteMenuJSRec($menu, $filteredcontent, 0);
$menu .= "];\n";
$menu .= "\ncmThemeIE.folderLeft = '';\n";
$menu .= "\ncmThemeIE.folderRight = '<img alt=\"\" src=\"".$config['root_url']."/modules/JSCookMenu/JSCookMenu/themes/ThemeIE/arrow.gif\" />';\n";
$menu .= "\ncmThemeIE.itemLeft = '';\n";
if ($horizontal)
{
$menu .= "\ncmDraw ('jscookmenuid', jscMenuArr, 'hbr', cmThemeIE, 'ThemeIE');\n";
}
else
{
$menu .= "\ncmDraw ('jscookmenuid', jscMenuArr, 'vbr', cmThemeIE, 'ThemeIE');\n";
}
$menu .= "--></__script>";
}
function WriteMenuJSRec(&$menu, &$filteredcontent, $recdepth)
{
#Safety check
$recdepth++;
if ($recdepth > 100)
{
#Uh-oh. There must be a bug. Stop to avoid exhausting the stack memory.
return;
}
while ($onecontent = current($filteredcontent))
{
if ($onecontent->Type() == 'separator')
{
$menu .= "_cmSplit";
}
else
{
$menu .= "[";
// if this is a section header, the URL is simple '#'
$menu .= "'', '".$onecontent->MenuText()."', '".$onecontent->GetURL()."', '_top', '".$onecontent->MenuText()."'";
}
$nextcontent = next($filteredcontent);
if ($nextcontent)
{
$currmenudepth = count(split('\.', $onecontent->Hierarchy()));
$nextmenudepth = count(split('\.', $nextcontent->Hierarchy()));
#if next content is deeper
if ($nextmenudepth > $currmenudepth)
{
$menu .= ", ";
//next($filteredcontent);
$result = $this->WriteMenuJSRec($menu, $filteredcontent, $recdepth);
$menu .= "]";
$onecontent = current($filteredcontent);
$nextcontent = next($filteredcontent);
if ($nextcontent)
{
$currmenudepth = count(split('\.', $onecontent->Hierarchy()));
$nextmenudepth = count(split('\.', $nextcontent->Hierarchy()));
#content is at same depth
if ($nextmenudepth == $currmenudepth)
{
$menu .= "], ";
}
else #next content is shallower
{
if ($result == 0)
{
$menu .= ", ";
}
else
{
prev($filteredcontent);
return $result - 1;
}
}
}
}
#else if next content is at same depth
elseif ($nextmenudepth == $currmenudepth)
{
if ($onecontent->Type() == 'separator')
{
$menu .= ", ";
}
else
{
$menu .= "], ";
}
}
else #next content is shallower
{
if ($onecontent->Type() != 'separator')
{
$menu .= "]";
}
prev($filteredcontent);
return $currmenudepth - $nextmenudepth - 1;
}
}
}
$menu .= "]";
return 0;
}
}
?>
Code: Select all
var cmThemeIEBase = '/modules/JSCookMenu/JSCookMenu/themes/ThemeIE/';
