Wiki source for WikkaMenus


Show raw source

==== Wikka Menus ====
{{lastedit}}

This is an improved version of a module for creating and managing **custom Wikka menus**.
The module uses a dedicated ##wikka_menus## table, in which the settings for several menus can be stored, along with their CSS selectors.
This version allows menus to be created, modified, (safely) renamed and (safely) deleted.
The output is an unordered list (##<ul>##) of menu items, which can then be formatted as a horizontal or vertical menu through the appropriate [[http://www.sovavsiti.cz/css/horizontal_menu.html | CSS style]].

== Menu items: more than links ==
Beside adding links, Wikka administrators will be able to add items such as //text//, //images// and //action-generated content// (provided there are actions that do the job).
In order to use actions in WikkaMenus, the current //system links// that are present in the header and footer menu have to be 'modularized', i.e. saved as actions so as to let Wikka admins free to decide whether to display them or not.

<<See WikkaMenulets for more information on action-generated content for menu items<<::c::

==Why a menu table?==
a) it is much **safer** having a script modify single table entries than write into the Wikka configuration file (which contains //all// system settings).
a) it is possible to create as many menus as needed, without cluttering up the system configuration, and store each menu in the table along with a CSS class/id that will determine its appearance on the page;


Here's how the menu interface looks like:
----
""
<h3>Menu Configuration</h3>
<br />

Please enter menu items on separate lines. <br /> You can use on each line: <br /> <strong>camelcase links</strong> like: <tt>PageIndex</tt> <br /> <strong>forced links</strong> like: <tt>[[RecentChanges | What's new?]]</tt> <br /> <strong>actions</strong> like: <tt>{{who}}</tt> <br /> <br /> <form action="http://wikkaclean/Menu" method="post">
Menu: <strong>main_menu</strong><br /><input type="hidden" name="name" value="main_menu" /><textarea name="content" rows="6" cols="30">HomePage
PageIndex
MyPages
RecentChanges
RecentlyCommented
[[UserSettings | Login]]</textarea><br /><input type="submit" name="operation" value="Update Menu" style="width: 120px" accesskey="s" /><input type="submit" name="operation" value="Delete Menu" style="width: 120px" /><br /><input type="text" name="newname" value="main_menu" style="width: 120px"><input type="submit" name="operation" value="Rename Menu" style="width: 120px" /><p> </p></form>
<form action="http://wikkaclean/Menu" method="post">
Menu: <strong>logged_in_menu</strong><br /><input type="hidden" name="name" value="logged_in_menu" /><textarea name="content" rows="6" cols="30">HomePage
PageIndex
RecentChanges
SkinEditor
TestTest
IncludeRemote
[[Menu | MenuConfig]]
UserAdminTest
[[UserSettings | Logout]]
{{who}}</textarea><br /><input type="submit" name="operation" value="Update Menu" style="width: 120px" accesskey="s" /><input type="submit" name="operation" value="Delete Menu" style="width: 120px" /><br /><input type="text" name="newname" value="logged_in_menu" style="width: 120px"><input type="submit" name="operation" value="Rename Menu" style="width: 120px" /><p> </p></form>
<form action="http://wikkaclean/Menu" method="post">
Menu: <strong>footer_menu</strong><br /><input type="hidden" name="name" value="footer_menu" /><textarea name="content" rows="6" cols="30">
{{edit}}
{{history}}
{{revisions}}
{{xmlrevisions}}
{{owner}}
{{acl}}
{{referrers}}
{{search}}
</textarea><br /><input type="submit" name="operation" value="Update Menu" style="width: 120px" accesskey="s" /><input type="submit" name="operation" value="Delete Menu" style="width: 120px" /><br /><input type="text" name="newname" value="footer_menu" style="width: 120px"><input type="submit" name="operation" value="Rename Menu" style="width: 120px" /><p> </p></form>
<h5> Create a new menu </h5>
<form action="http://wikkaclean/Menu" method="post">
<table><tr><td>Menu name:</td><td><input type="text" name="newname" value="new_menu_name" style="width: 120px"></td></tr><tr><td>CSS class:</td><td> <input type="text" name="css" value="css_class" style="width: 120px"><td></tr></table><input type="submit" name="operation" value="Create Menu" style="width: 120px" /><br /></form>
""
----

====Installation====

==1. Create the table==
''Updated 2004-11-16: field names modified''

You will need to change your wikka prefix, e.g. "wikka_", to match your configuration.
Menus are identified through their ##name## which is unique, ##content## is a ##\n##-separated list of links, ##css_class## is a CSS selector. Different menus can have the same ##css_class##.
''I removed the sample INSERT, since new menus can be built using the interface below''

%%
CREATE TABLE `wikka_menus` (
`name` varchar(20) NOT NULL default '',
`content` varchar(255) NOT NULL default '',
`css_class` varchar(20) NOT NULL default '',
UNIQUE KEY `name` (`name`)
) TYPE=MyISAM;
%%

==2. Add the menu functions in ##libs/Wakka.class.php##==
''Updated 2004-11-17: more compact functions''


%%(php)

function LoadMenu($name) {
$content = $this->LoadSingle("SELECT * FROM ".$this->config["table_prefix"]."menus WHERE name = '".$name."'");
return $content;
}

function LoadAllMenus() {
$menurow = $this->LoadAll("SELECT * FROM ".$this->config["table_prefix"]."menus");
return $menurow;
}

function SaveMenu($name, $content) {
$this->Query("UPDATE ".$this->config["table_prefix"]."menus SET content ='".mysql_real_escape_string(trim(str_replace("\r", "", $content)))."' WHERE name = '".$name."' LIMIT 1");
}

function MenuExists($name) {
if ($this->LoadMenu($name)){
return true;
}
}

function RenameMenu($oldname, $newname) {
$this->Query("UPDATE ".$this->config["table_prefix"]."menus SET name = '".$newname."' WHERE name = '".$oldname."' LIMIT 1");
}

function DeleteMenu($name) {
$this->Query("DELETE FROM ".$this->config["table_prefix"]."menus WHERE name = '".$name."' LIMIT 1");
}

function CreateMenu($name, $css_class) {
$this->Query("INSERT INTO ".$this->config["table_prefix"]."menus SET name = '".mysql_real_escape_string($name)."', content = '', css_class = '".mysql_real_escape_string($css_class)."'");
}

function TrimMenu($list) {
foreach (explode("\n", $list) as $line) {
$line = trim($line);
$trimmed_list .= $line."\n";
}
return $trimmed_list;
}

function PrintMenu($name) {
if ($menurow = $this->LoadMenu($name)) {
$menu = "<ul class=\"".$menurow["css_class"]."\">";
foreach (explode("\n", $menurow["content"]) as $menuitem){ $menu .="<li>".$this->Format($menuitem)."</li>\n";
}
$menu .= "</ul>\n";
return $menu;
}
}
%%

==3. Create the menu configuration interface (##action/menu.php##) ==
''Updated 2004-11-16: Menus can be now created, deleted, renamed and modified''

%%(php)

// Menu Configuration Interface
// Version 1.0

<h3>Menu Configuration</h3>
<br />

<?php
if ($this->IsAdmin()) {
switch ($_POST["operation"]) {
case "Create Menu":
if ($this->MenuExists($_POST["newname"])) {
echo $this->Format("<<**Sorry!** --- A menu named \"".$_POST["newname"]."\" already exists. --- Please choose another name<<::c::--- --- ");
} else {
$this->CreateMenu($_POST["newname"], $_POST["css"]);
echo $this->Format("<<**Thanks!** --- Menu \"".$_POST["newname"]."\" has been created<<::c:: --- ");
}
break;

case "Delete Menu":
echo $this->Format("<<**Confirmation required**<<::c:: --- Do you really want to delete **".$_POST["name"]."**? --- --- ");
$formdelete = '<input type="hidden" name="name" value="'.$_POST["name"].'" />'.
'<input type="submit" name="operation" value="Confirm Deletion" style="width: 120px" accesskey="s" />'.
'<input type="button" value="Cancel" onClick="history.back();" style="width: 120px" /><p> </p>';
print $this->FormOpen("","","post");
print $formdelete;
print $this->FormClose();
break;

case "Confirm Deletion":
$this->DeleteMenu($_POST["name"]);
echo $this->Format("<<**Thanks!** --- Menu \"".$_POST["name"]."\" has been deleted<<::c:: --- ");
break;

case "Rename Menu":
if ($this->MenuExists($_POST["newname"])) {
echo $this->Format("<<**Sorry!** --- A menu named \"".$_POST["newname"]."\" already exists. --- Please choose another name<<::c:: --- --- ");
} else {
echo $this->Format("<<**Confirmation required**<<::c:: --- Do you really want to rename **".$_POST["name"]."** as **".$_POST["newname"]."**? --- --- ");
$formrename = '<input type="hidden" name="oldname" value="'.$_POST["name"].'" />'.
'<input type="hidden" name="newname" value="'.$_POST["newname"].'" />'.
'<input type="submit" name="operation" value="Confirm Rename" style="width: 120px" accesskey="s" />'.
'<input type="button" value="Cancel" onClick="history.back();" style="width: 120px" /><p> </p>';
print $this->FormOpen("","","post");
print $formrename;
print $this->FormClose();
}
break;

case "Confirm Rename":
$this->RenameMenu($_POST["oldname"], $_POST["newname"]);
echo $this->Format("<<**Thanks!** --- Menu has been renamed as \"".$_POST["newname"]."\"<<::c:: --- --- ");
break;

case "Update Menu":
$this->SaveMenu($_POST["name"], $this->TrimMenu($_POST["content"]));
echo $this->Format("<<**Menu configuration stored** --- Thanks for updating \"".$_POST["name"]."\"!<<::c:: --- --- ");
break;
}

// load stored menus and print menu forms
echo $this->Format('Please enter menu items on separate lines. --- You can either use //""CamelCase"" links// like ##""PageIndex""## --- or //forced links// like: ##""[[http://www.mydomain.com | External Link]]""## --- --- --- ');
$allmenus = $this->LoadAllMenus();
foreach ($allmenus as $item) {
$formarray[$item["name"]] = 'Menu: <strong>'.$item["name"].'</strong><br />'.
'<input type="hidden" name="name" value="'.$item["name"].'" />'.
'<textarea name="content" rows="6" cols="30">'.$item["content"].'</textarea><br />'.
'<input type="submit" name="operation" value="Update Menu" style="width: 120px" accesskey="s" />'.
'<input type="submit" name="operation" value="Delete Menu" style="width: 120px" /><br />'.
'<input type="text" name="newname" value="'.$item["name"].'" style="width: 120px">'.
'<input type="submit" name="operation" value="Rename Menu" style="width: 120px" /><p> </p>';
print $this->FormOpen("","","post");
echo $formarray[$item["name"]];
print($this->FormClose());
}

// "Create menu" form
$newmenuform = '<table><tr>'.
'<td>Menu name:</td><td><input type="text" name="newname" value="new_menu_name" style="width: 120px"></td></tr>'.
'<tr><td>CSS class:</td><td> <input type="text" name="css" value="css_class" style="width: 120px"><td></tr></table>'.
'<input type="submit" name="operation" value="Create Menu" style="width: 120px" /><br />';
echo $this->Format("== Create a new menu ==");
print $this->FormOpen("","","post");
echo $newmenuform;
print($this->FormClose());

} else {
print("<em>Sorry, only Wikka Administrators can modify the Menu configuration.</em>");
}

?>
%%

== 4. Create the appropriare CSS styles ==

Here's a basic example for formatting a Wikka Menu as a horizontal menu. Change the CSS class (##main_menu##) to match the one you specified when creating a menu.

%%
.main_menu {
width: 100%;
list-style-type: none;
}
.main_menu li {
padding: 2pt;
float: left;
width: auto;
margin-right: 3pt;
text-align: center;
}
.main_menu .exttail {
visibility: hidden;
}
%%

== 5. Use the menus in your wiki pages==

Once you've set the appropriate [[http://www.sovavsiti.cz/css/horizontal_menu.html | CSS styles]], two different usages of custom Wikka Menus are possible:

You can either print your menus in the **page header**, by modifying ##actions/header.php as follows##
''Updated 2004-11-17: typo in previous version - sorry!''

**original ##actions/header.php##**
%%(php)
<?php echo $this->Link($this->config["root_page"]); ?> ::
<?php
if ($this->GetUser()) {
echo $this->config["logged_in_navigation_links"] ? $this->Format($this->config["logged_in_navigation_links"])." :: " : "";
echo "You are ".$this->Format($this->GetUserName());
} else {
echo $this->config["navigation_links"] ? $this->Format($this->config["navigation_links"]) : "";
}
?>
%%

**modified ##actions/header.php##**
%%(php)
<?php
if ($this->GetUser()) {
echo $this->PrintMenu("logged_in_menu");
} else {
echo $this->PrintMenu("main_menu");
}
?>
%%

or use them in the **page body**, through a simple action ##action/printmenu.php## which can be called on the page with a syntax like ##""{{printmenu name="main_menu"}}""##
''Updated 2004-11-16: replaced $type with $name''

##actions/printmenu.php##
%%(php)
<?php
// Print Menu action
echo $this->PrintMenu($name);
?>
%%



----
== Notes ==
- The code above can be easily modified to allow the creation of an indefinite number of custom menus, each with its name, content and css selector.
- The same approach might be used to allow users to modify their own custom menu (which would be stored in a dedicated row of users table)
- I wonder if menus are better handled by CSS ##id##'s or ##classes##: do you think menus of the same type are susceptible to occur more than once on a page?
- Improvements and suggestions for the code above are welcome :)

== To Do ==
- Integration with current menu configurations

-- DarTar

----
CategoryDevelopmentArchitecture
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki