Menú similar a las barras de herramientas de windows

edited noviembre 2009 in FAQ
vamos a crear un menu dinamico alimentado de 2 standar form
más usuarios y perfiles de usuarios

primero creamos nuestra tabla de usuarios o login, perfiles, menu y controladores
CREATE TABLE `usuarios` (                                                
        `id` int(4) NOT NULL auto_increment,                                   
        `username` varchar(50) collate utf8_bin default NULL,                  
        `password` varchar(100) collate utf8_bin default NULL,      
        `perfiles_id` int(4) default NULL,                                     
        `estado` char(1) collate utf8_bin default NULL,                        
        PRIMARY KEY  (`id`)                                                    
      );
CREATE TABLE `perfiles` (                                               
        `id` int(4) NOT NULL auto_increment,                                  
        `nombre` varchar(100) collate utf8_bin default NULL,                  
        PRIMARY KEY  (`id`)                                                   
          );
CREATE TABLE `menus` (                                   
      `id` int(4) NOT NULL auto_increment,                   
      `title` varchar(100) default NULL,                     
      `nombre` varchar(100) default NULL,                    
      PRIMARY KEY  (`id`)                                    
        );
CREATE TABLE `controladores` (                                           
       `id` int(4) NOT NULL auto_increment,                                   
       `perfiles_id` int(4) default NULL,                                     
       `menus_id` int(4) default NULL,                                        
       `nombre` varchar(100) collate utf8_bin default NULL,                   
       `nombrelargo` varchar(150) collate utf8_bin default NULL,              
       `mostrar` char(1) collate utf8_bin default NULL,                       
       PRIMARY KEY  (`id`)                                                    
               );

los campos nombreslargo es el title q se mostrara al usuario.

ahora procederemos a crear standarform de controladores y usuarios las otras 2 tablas se pueden alimentar directo de la base ya que solo se ocupara una sola vez. ej:
insert into perfiles(nombre) values ('Admin');
insert into perfiles(nombre) values ('Usuarios');

insert  into `menus`(`id`,`title`,`nombre`) values (1,'archivo','Archivo'),(2,'administracion','Administracion'),(3,'opciones','Opciones'),(4,'informes','Informes'),(5,'ayuda','Ayuda');

ahora solo deben copiar y pegar
cremos una css llamada menus.css
div.menuBar,
div.menuBar a.menuButton,
div.menu,
div.menu a.menuItem {
  font-family: "MS Sans Serif", Arial, sans-serif;
  font-size: 8pt;
  font-style: normal;
  font-weight: normal;
  color: #000000;
}
div.menuBar {
  background-color: #d0d0d0;
  border: 2px solid;
  border-color: #f0f0f0 #909090 #909090 #f0f0f0;
  padding: 4px 2px 4px 2px;
  text-align: left;
}
div.menuBar a.menuButton {
  background-color: transparent;
  border: 1px solid #d0d0d0;
  color: #000000;
  cursor: default;
  left: 0px;
  margin: 1px;
  padding: 2px 6px 2px 6px;
  position: relative;
  text-decoration: none;
  top: 0px;
  z-index: 100;
}
div.menuBar a.menuButton:hover {
  background-color: transparent;
  border-color: #f0f0f0 #909090 #909090 #f0f0f0;
  color: #000000;
}
div.menuBar a.menuButtonActive,
div.menuBar a.menuButtonActive:hover {
  background-color: #a0a0a0;
  border-color: #909090 #f0f0f0 #f0f0f0 #909090;
  color: #ffffff;
  left: 1px;
  top: 1px;
}
div.menu {
  background-color: #d0d0d0;
  border: 2px solid;
  border-color: #f0f0f0 #909090 #909090 #f0f0f0;
  left: 0px;
  padding: 0px 1px 1px 0px;
  position: absolute;
  top: 0px;
  visibility: hidden;
  z-index: 101;
}
div.menu a.menuItem {
  color: #000000;
  cursor: default;
  display: block;
  padding: 3px 1em;
  text-decoration: none;
  white-space: nowrap;
}
div.menu a.menuItem:hover, div.menu a.menuItemHighlight {
  background-color: #000080;
  color: #ffffff;
}
div.menu a.menuItem span.menuItemText {}
div.menu a.menuItem span.menuItemArrow {
  margin-right: -.75em;
}
div.menu div.menuItemSep {
  border-top: 1px solid #909090;
  border-bottom: 1px solid #f0f0f0;
  margin: 4px 2px;
}
lo crean dentro de public/css/menus.css

lo mismo, pero ahora crean otro archivo en esta path
public/javascript/menus.js
/*
 *	funcion que hace cambiar a mayúsculas cada strind de un obj (input)
 */
function Mayusculas(c){
	c.value = c.value.toUpperCase();
}

function Browser() {
  var ua, s, i;
  this.isIE    = false;  
  this.isNS    = false;  
  this.version = null;

  ua = navigator.userAgent;

  s = "MSIE";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isIE = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  s = "Netscape6/";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  // Treat any other "Gecko" browser as NS 6.1.

  s = "Gecko";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = 6.1;
    return;
  }
}

var browser = new Browser();

//----------------------------------------------------------------------------
// Code for handling the menu bar and active button.
//----------------------------------------------------------------------------

var activeButton = null;

// Capture mouse clicks on the page so any active button can be
// deactivated.

if (browser.isIE)
  document.onmousedown = pageMousedown;
else
  document.addEventListener("mousedown", pageMousedown, true);

function pageMousedown(event) {
  var el;
  if (activeButton == null)
    return;

  if (browser.isIE)
    el = window.event.srcElement;
  else
    el = (event.target.tagName ? event.target : event.target.parentNode);

  if (el == activeButton)
    return;

  if (getContainerWith(el, "DIV", "menu") == null) {
    resetButton(activeButton);
    activeButton = null;
  }
}

function buttonClick(event, menuId) {
  var button;

  if (browser.isIE)
    button = window.event.srcElement;
  else
    button = event.currentTarget;

  button.blur();

  if (button.menu == null) {
    button.menu = document.getElementById(menuId);
    menuInit(button.menu);
  }

  if (activeButton != null)
    resetButton(activeButton);

  if (button != activeButton) {
    depressButton(button);
    activeButton = button;
  }
  else
    activeButton = null;

  return false;
}

function buttonMouseover(event, menuId) {
  var button;

  if (browser.isIE)
    button = window.event.srcElement;
  else
    button = event.currentTarget;

  if (activeButton != null && activeButton != button)
    buttonClick(event, menuId);
}

function depressButton(button) {
  var x, y;

  button.className += " menuButtonActive";

  x = getPageOffsetLeft(button);
  y = getPageOffsetTop(button) + button.offsetHeight;

  if (browser.isIE) {
    x += button.offsetParent.clientLeft;
    y += button.offsetParent.clientTop;
  }

  button.menu.style.left = x + "px";
  button.menu.style.top  = y + "px";
  button.menu.style.visibility = "visible";
}

function resetButton(button) {
  removeClassName(button, "menuButtonActive");

  if (button.menu != null) {
    closeSubMenu(button.menu);
    button.menu.style.visibility = "hidden";
  }
}


function menuMouseover(event) {
  var menu;
  if (browser.isIE)
    menu = getContainerWith(window.event.srcElement, "DIV", "menu");
  else
    menu = event.currentTarget;

  if (menu.activeItem != null)
    closeSubMenu(menu);
}

function menuItemMouseover(event, menuId) {
  var item, menu, x, y;
  if (browser.isIE)
    item = getContainerWith(window.event.srcElement, "A", "menuItem");
  else
    item = event.currentTarget;
  menu = getContainerWith(item, "DIV", "menu");

  if (menu.activeItem != null)
    closeSubMenu(menu);
  menu.activeItem = item;

  item.className += " menuItemHighlight";

  if (item.subMenu == null) {
    item.subMenu = document.getElementById(menuId);
    menuInit(item.subMenu);
  }

  x = getPageOffsetLeft(item) + item.offsetWidth;
  y = getPageOffsetTop(item);

  var maxX, maxY;

  if (browser.isNS) {
    maxX = window.scrollX + window.innerWidth;
    maxY = window.scrollY + window.innerHeight;
  }
  if (browser.isIE && browser.version < 6) {
    maxX = document.body.scrollLeft + document.body.clientWidth;
    maxY = document.body.scrollTop  + document.body.clientHeight;
  }
  if (browser.isIE && browser.version >= 6) {
    maxX = document.documentElement.scrollLeft + document.documentElement.clientWidth;
    maxY = document.documentElement.scrollTop  + document.documentElement.clientHeight;
  }
  maxX -= item.subMenu.offsetWidth;
  maxY -= item.subMenu.offsetHeight;

  if (x > maxX)
    x = Math.max(0, x - item.offsetWidth - item.subMenu.offsetWidth
      + (menu.offsetWidth - item.offsetWidth));
  y = Math.max(0, Math.min(y, maxY));

  item.subMenu.style.left = x + "px";
  item.subMenu.style.top  = y + "px";
  item.subMenu.style.visibility = "visible";

  if (browser.isIE)
    window.event.cancelBubble = true;
  else
    event.stopPropagation();
}

function closeSubMenu(menu) {
  if (menu == null || menu.activeItem == null)
    return;

  if (menu.activeItem.subMenu != null) {
    closeSubMenu(menu.activeItem.subMenu);
    menu.activeItem.subMenu.style.visibility = "hidden";
    menu.activeItem.subMenu = null;
  }
  removeClassName(menu.activeItem, "menuItemHighlight");
  menu.activeItem = null;
}

function menuInit(menu) {
  var itemList, spanList
  var textEl, arrowEl;
  var itemWidth;
  var w, dw;
  var i, j;

  if (browser.isIE) {
    menu.style.lineHeight = "2.5ex";
    spanList = menu.getElementsByTagName("SPAN");
    for (i = 0; i < spanList.length; i++)
      if (hasClassName(spanList[i], "menuItemArrow")) {
        spanList[i].style.fontFamily = "Webdings";
        spanList[i].firstChild.nodeValue = "4";
      }
  }

  itemList = menu.getElementsByTagName("A");
  if (itemList.length > 0)
    itemWidth = itemList[0].offsetWidth;
  else
    return;

  for (i = 0; i < itemList.length; i++) {
    spanList = itemList[i].getElementsByTagName("SPAN")
    textEl  = null
    arrowEl = null;
    for (j = 0; j < spanList.length; j++) {
      if (hasClassName(spanList[j], "menuItemText"))
        textEl = spanList[j];
      if (hasClassName(spanList[j], "menuItemArrow"))
        arrowEl = spanList[j];
    }
    if (textEl != null && arrowEl != null)
      textEl.style.paddingRight = (itemWidth 
        - (textEl.offsetWidth + arrowEl.offsetWidth)) + "px";
  }

  if (browser.isIE) {
    w = itemList[0].offsetWidth;
    itemList[0].style.width = w + "px";
    dw = itemList[0].offsetWidth - w;
    w -= dw;
    itemList[0].style.width = w + "px";
  }
}

function getContainerWith(node, tagName, className) {
  while (node != null) {
    if (node.tagName != null && node.tagName == tagName &&
        hasClassName(node, className))
      return node;
    node = node.parentNode;
  }

  return node;
}

function hasClassName(el, name) {
  var i, list;
  list = el.className.split(" ");
  for (i = 0; i < list.length; i++)
    if (list[i] == name)
      return true;

  return false;
}

function removeClassName(el, name) {
  var i, curList, newList;
  if (el.className == null)
    return;
  newList = new Array();
  curList = el.className.split(" ");
  for (i = 0; i < curList.length; i++)
    if (curList[i] != name)
      newList.push(curList[i]);
  el.className = newList.join(" ");
}

function getPageOffsetLeft(el) {
  var x;
  x = el.offsetLeft;
  if (el.offsetParent != null)
    x += getPageOffsetLeft(el.offsetParent);

  return x;
}

function getPageOffsetTop(el) {
  var y;
  y = el.offsetTop;
  if (el.offsetParent != null)
    y += getPageOffsetTop(el.offsetParent);

  return y;
}

si son ordenados crean carpetas dentro de estas si tienen muchos archivos.

ahora solo debemos agregarlas al default/views/index.phtml
	<?php echo stylesheet_link_tag('menus', 'use_variables: true') ?>
	<?php echo javascript_include_tag("menus"); ?>

ahora creamos un standarform de controladores
<?php	
class ControladoresController extends StandardForm {
	public $scaffold	=	true;
	//public $template	=	"menu";
	public function __construct(){
		error_reporting(E_ALL ^ E_NOTICE);
		//id           int(4)
		$this->set_hidden("id");      
		//perfiles_id  int(4)     
		//nombre       varchar(100)
		$this->set_size("nombre", 30);
		$this->set_maxlength("nombre", 100);
		//nombrelargo  varchar(150)
		$this->set_size("nombrelargo", 40);
		$this->set_maxlength("nombrelargo", 150);
		//mostrar char(1)
		$this->set_combo_static("mostrar", array(array("S", "SI"), array("N", "NO")));			
	}
}	
?>


ahora creamos un loyouts llamado menu.phtml ("default/views/menu.phtml")
<?php $perfiles_id	=	Session::get("perfiles_id"); $sw=true; ?>
<center>
<div class="menuBar" style="width:80%;">
  <div align="left">
  <?php foreach($Menus->find() as $menu): ?>
  <?php
	$title		=	$menu->nombre;
	$title_id	=	$menu->title."Menu";
?>
    <a class="menuButton" href="" onclick="return buttonClick(event, '<?php echo $title_id ?>');" onmouseover="buttonMouseover(event, '<?php echo $title_id ?>');"><?php echo $title ?></a>
    <?php endforeach; ?>
  </div>
</div>

<div align="left">
  <?php foreach($Menus->find() as $menu): ?>
  <?php
	$title		=	$menu->title;
	$title_id	=	$menu->title."Menu";
?>
</div>
<div id="<?php echo $title_id ?>" class="menu" onmouseover="menuMouseover(event)">
	<div align="left">
	  <?php foreach ($Controladores->find("perfiles_id = $perfiles_id and mostrar = 'S' and menus_id = $menu->id", "order: nombrelargo") as $controlador): ?>
	  <a class="menuItem" href='<?php echo get_kumbia_url("perfil/index/$controlador->nombre") ?>'><?php echo $controlador->nombrelargo ?></a>
      <?php endforeach; ?>
      <?php if($sw==true){ ?>
    </div>
	<div class="menuItemSep"></div>
		<div align="left"><a class="menuItem" href="<?php echo get_kumbia_url("login/salir") ?>">Salir</a>
          <?php } $sw=false;?>
        </div>
</div>
<?php endforeach; ?>

<!-- Centro -->	
<?php content() ?>
</center>

con esto estamos casi listo solo debes obtener el perfil del usuario cuando inicie session algo como esto
	public function valida(){
		$username		=	$this->request("username");
		$password		=	sha1($this->request("password"));
		$auth= new Auth("model","class: Usuarios", "username: $username","password: $password", "estado: A");
		if($auth->authenticate()){
			$login		=	$auth->get_identity();
			$usuario	=	$this->Usuarios->find($login["id"]);
			$comunas_id	=	$login["comunas_id"];
			$comuna		=	$this->Comunas->find_first("id = $comunas_id");
			Session::set("usuarios_id", $login["id"]);
			Session::set("usuarios_nombres", $login["nombres"]);
			Session::set("usuarios_apellidos", $login["apellidos"]);
			Session::set("perfiles_id", $login["perfiles_id"]);	
.
.
.
.
.

y estamos listo solo debes agregar a todas tus paginas el template menu
asi
class MipaginaController [ApplicationController o StandarForm]{
 public $template = "menu";

}


se me olvidaba deben crear un controlador de esta manera con el mismo nombre. hace que los link funcione
<?php
class PerfilController extends ApplicationController  {
	/**
	 * Redirecciona al menú que corresponda
	 * y le asigna una css según corresponda
	 *
	 * @param int $menu
	 */
	public function index($items,$action='index',$id=''){
		$perfiles_id	=	null;
		$perfiles_id	=	Session::get("perfiles_id");
		if ($action!="index"){
			$controlador=	"$items/$action";
		}else{
			$controlador=	$items;
		}
		if($perfiles_id	==	null){
			$this->redirect("valida");
		}elseif($controlador	=	$this->Controladores->find_first("nombre = '$controlador' and perfiles_id = $perfiles_id")){	
			return $this->route_to("controller: $items", "action: $action", "id: $id");
		}else{
			Flash::warning("Seleccione un item del menú");
		}
	}
}
?>
suerte y espero q les funcione bien ya q ami me ha sido de mucha utilidad.
los colores del menu estan en la Hoja de estilo.

Comentarios

  • edited 2:17
    Hola Fiedel

    Estoy tratando de instalar tu scrip pero me encuentro con algunas dudas y no he podido resolveralas, me gustaria y me pudieras dar una ayuda con esto.

    Hay una fucion valida parece que le faltan dos } }
    estamos listo solo debes agregar a todas tus paginas el template menu
    asi
    Esta parte no la entiendo mucho.

    Me gustaria tener la estructura de los archivos como quedan al final.

    Un ejemlpo del menu.
    Como debo iniciar la pagina o que debo adicionar para que esto funcione.

    Te agradezco por la colaboracion que me puedas dar.
    Soy nuevo en esto pero quiero aprender.
    Instale la version de kumbia 5.0

    Gracias
    Orlando
  • edited 2:17
    la funcion valida la debes crear tu
    ese es un ejemplo, lo unico importante es crear la variable de session
    perfiles_id
    Session::set("perfiles_id", $login["perfiles_id"]);   
    

    es cuando el usuario se autentifica antes de ingresar a nuestra app

    si tienes problemas no dudes de consultar,

    suetre!!!
  • hola, estoy viendo lo que dices,y tengo unas dudas:

    La funcion valida en que controlador debe de ir?

    para hacer el login como tengo que redireccionar al controlador perfiles?

    y en el index de perfiles que tengo que poner para que me ponga el menu que corresponde al perfil?

    soy nuevo en kumbia, gracias
  • edited 2:17
    si te fijas nombre que archivos hay q modificar ej: default/views/index.phtml

    no todos son controller, lo otro que este ejemplo esta obsoleto, ya q es de la version 0.5 y la nueva version esta beta, pero casi lista,

    cambio un poco la estructura de ficheros.
Sign In or Register to comment.