您的位置:首页 > 其它

Joomla模块学习之后台mod_menu模块

2011-01-05 15:56 288 查看
Joomla模块学习之后台mod_menu模块









后台管理模块效果图








原理:

后台模块菜单管理主要通过两个关键类Jtree和JNode建立菜单间的关联关系.

通过一个根级别菜单,所有的菜单都是根菜单的子级,或者更低级别



如图所示:







例如 :根级别(root)的子级中包括title名为"组件"(红线)的子级,而titile名为"组件"(红线)的子级则包括title名为"旗帜广告"的子级."旗帜广告"的子级有包括"广告管理","客户管理"等子级....



root----->"组件"------>旗帜广告------->广告管理,客户管理



菜单模块所有的菜单都是从根级向下延伸,建立关联关系后通过递归,迭代出所有的菜单





关键代码:



创建根目录对象

$menu = new JAdminCSSMenu();


class JAdminCSSMenu extends JTree
{
    ......
    function __construct()
    {
	    $this->_root = new JMenuNode('ROOT');
	    $this->_current = & $this->_root;
    }
    ......
}


class JMenuNode extends JNode
{
    ......
    function __construct($title, $link = null, $class = null, $active = false)
    {
        $this->title	= $title;
	    $this->link  = JFilterOutput::ampReplace($link);
	    $this->class  = $class;
	    $this->active  = $active;
	    $this->id  = str_replace(" ","-",$title);
    }
    ......
}








添加节点

$menu->addChild(new JMenuNode(JText::_('Site')), true);
添加下划线(class参数指定为separator)
$menu->addChild(new JMenuNode(null, null, 'separator', false));
(JTree代码)
function addChild(&$node, $setCurrent = false)
{

        $this->_current->addChild($node);

        if ($setCurrent) {  //是否更改父节点
	         $this->_current =& $node;
        }
}
(JNode代码)
function addChild( &$node )
{
        $node->setParent($this); //设置节点的父级
         $this->_children[] = & $node;  
}

function setParent( &$node )
{
        $this->_parent = & $node;
}




//当前菜单节点下子节点添加完毕,
//返回上一级别

$menu->getParent();


(JTree代码)
function getParent()
{
        $this->_current =& $this->_current->getParent();
}

(JNode代码)
function &getParent()
{
        return $this->_parent;
}


组件管理,添加组件节点

$menu->addChild(new JMenuNode(JText::_('Components')), true);

//根据条件加载所有组件信息
$query = 'SELECT *' .
	' FROM #__components' .
	' WHERE '.$db->NameQuote( 'option' ).' <> "com_frontpage"' .
	' AND '.$db->NameQuote( 'option' ).' <> "com_media"' .
	' AND enabled = 1' .
	' ORDER BY ordering, name';
		

	$db->setQuery($query);
	$comps = $db->loadObjectList(); // component list




按相同父节点将组件分类
$subs = array(); // sub menus
$langs = array(); // additional language files to load

// first pass to collect sub-menu items
foreach ($comps as $row)
{
    if ($row->parent)
    {
        if (!array_key_exists($row->parent, $subs)) {
	        $subs[$row->parent] = array ();
	    }
		
        $subs[$row->parent][] = $row;
	    $langs[$row->option.'.menu'] = true;
    } elseif (trim($row->admin_menu_link)) {
	    $langs[$row->option.'.menu'] = true;
    }
}

// Load additional language files
if (array_key_exists('.menu', $langs)) {
    unset($langs['.menu']);
}
        
//加载语言信息
foreach ($langs as $lang_name => $nothing) {
    $lang->load($lang_name);
}


foreach ($comps as $row)
{
    	if ($editAllComponents | $user->authorize('administration', 'edit', 'components', $row->option))
    	{
		    if ($row->parent == 0 && (trim($row->admin_menu_link) || array_key_exists($row->id, $subs)))
		    {	
			    $text = $lang->hasKey($row->option) ? JText::_($row->option) : $row->name;
			    $link = $row->admin_menu_link ? "index.php?$row->admin_menu_link" : "index.php?option=$row->option";
		
			    if (array_key_exists($row->id, $subs)) {
				    if($user->authorize($row->option, 'manage')){
					    $menu->addChild(new JMenuNode($text, $link, $row->admin_menu_img), true);
				    }
		
			
				    foreach ($subs[$row->id] as $sub) {
					    $key  = $row->option.'.'.$sub->name;
					    $text = $lang->hasKey($key) ? JText::_($key) : $sub->name;
					    $link = $sub->admin_menu_link ? "index.php?$sub->admin_menu_link" : null;
				
					    if($user->authorize($row->option, 'manage')){
						    $menu->addChild(new JMenuNode($text, $link, $sub->admin_menu_img));
					    }
				    }
			
				    if($user->authorize($row->option, 'manage')){
					    $menu->getParent();
				    }
			} else {
				if($user->authorize($row->option, 'manage')){
					$menu->addChild(new JMenuNode($text, $link, $row->admin_menu_img));
				}
			}
		}
	}
}
$menu->getParent();






渲染菜单

//渲染菜单
$menu->renderMenu('menu', '');


//渲染菜单
	function renderMenu($id = 'menu', $class = '')
	{
		global $mainframe;

		$depth = 1;

		if(!empty($id)) {
			$id='id="'.$id.'"';
		}

		if(!empty($class)) {
			$class='class="'.$class.'"';
		}

		/*
		 * Recurse through children if they exist
		 * 递归子级集合,判断当前节点是否有子级
		 */
		while ($this->_current->hasChildren())
		{
			echo "<ul ".$id." ".$class.">/n";
			foreach ($this->_current->getChildren() as $child)
			{
				$this->_current = & $child;
				$this->renderLevel($depth++);
			}
			echo "</ul>/n";
		}

		if ($this->_css) {
			// Add style to document head
			// 添加样式
			$doc = & JFactory::getDocument();
			$doc->addStyleDeclaration($this->_css);
		}
	}










递归节点

//递归子级菜单
	function renderLevel($depth)
	{
		/*
		 * Build the CSS class suffix
		 */
		$class = '';
		if ($this->_current->hasChildren()) {
			$class = ' class="node"';
		}

		if($this->_current->class == 'separator') {
			$class = ' class="separator"';
		}

		if($this->_current->class == 'disabled') {
			$class = ' class="disabled"';
		}

		/*
		 * Print the item
		 */
		echo "<li".$class.">";

		/*
		 * Print a link if it exists
		 */
		if ($this->_current->link != null) {  //添加当前节点的图标
			echo "<a class=/"".$this->getIconClass($this->_current->class)."/" href=/"".$this->_current->link."/">".$this->_current->title."</a>";
		} elseif ($this->_current->title != null) {
			echo "<a>".$this->_current->title."</a>/n";
		} else {
			echo "<span></span>";
		}

		/*
		 * Recurse through children if they exist
		 * 判断当前节点是否具有子节点,如果存在则递归renderLevel()函数
		 */
		while ($this->_current->hasChildren())
		{
			if ($this->_current->class) {
				echo '<ul id="menu-'.strtolower($this->_current->id).'"'.
					' class="menu-component">'."/n";
			} else {
				echo '<ul>'."/n";
			}
			foreach ($this->_current->getChildren() as $child)
			{
				$this->_current = & $child;
				//递归renderLevel()函数
				$this->renderLevel($depth++);
			}
			echo "</ul>/n";
		}
		echo "</li>/n";
	}








节点图标

function getIconClass($identifier)
	{
		global $mainframe;

		static $classes;

		// Initialize the known classes array if it does not exist
		// add by lin 20110105  如果不存在,初始化classes数组
		if (!is_array($classes)) {
			$classes = array();
		}

		/*
		 * If we don't already know about the class... build it and mark it
		 * known so we don't have to build it again
		 * add by lin 20110105  如果不存在Class,则构建它
		 */
		if (!isset($classes[$identifier])) {
			if (substr($identifier, 0, 6) == 'class:') {
				// We were passed a class name
				$class = substr($identifier, 6);
				$classes[$identifier] = "icon-16-$class";
			} else {
				// We were passed an image path... is it a themeoffice one?
				if (substr($identifier, 0, 15) == 'js/ThemeOffice/') {
					// Strip the filename without extension and use that for the classname
					$class = preg_replace('#/.[^.]*$#', '', basename($identifier));
					$classes[$identifier] = "icon-16-$class";
				} else {
					if ($identifier == null) {
						return null;
					}
					// Build the CSS class for the icon
					$class = preg_replace('#/.[^.]*$#', '', basename($identifier));
					$class = preg_replace( '#/./.[^A-Za-z0-9/./_/- ]#', '', $class);

					$this->_css  .= "/n.icon-16-$class {/n" .
							"/tbackground: url($identifier) no-repeat;/n" .
							"}/n";

					$classes[$identifier] = "icon-16-$class";
				}
			}
		}
		return $classes[$identifier];
	}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: