En este tutorial aprenderemos a crear nuestro propio panel lateral desplegable basado en jQuery. Lo haremos partiendo de cero y explicándolo como siempre paso a paso, de forma que todos podamos comprender cómo funciona. Todo ello inspirándonos en el panel lateral de Google Reader.

Autor:

Hola! Soy diseñador, programador web y cofundador de la startup Cokidoo, desarrollamos aplicaciones web a gran escala y comercio electrónico, aplicaciones para móviles y advertising. Puedes seguirme através de mi twitter y ver algunos de mis themes en Themeforest. También soy aficionado a la fotografía.
Descarga Demostración

Introducción: ¿Qué vamos a hacer?

No todo van a ser tutoriales alrededor de frameworks PHP, así pues retomamos los tutoriales relacionados con javascript y jQuery de la mano de este control en forma de panel lateral desplegable.

Para ello nos inspiraremos en el funcionamiento de Google Reader, del cual “copiaremos” en mayor o menor medida su funcionamiento y estética. Este será el aspecto final del control a crear:

Vista previa

La idea es que tengamos una lista de distintos canales RSS a cargar en la parte derecha, esta lista estará dentro de un panel lateral que se podrá colapsar o mostrar a gusto del propio usuario.

En este caso no cargaremos realmente fuentes RSS como hace Google Reader, para simplificar la tarea lo que haremos será cargar una web completa proveniente del elemento seleccionado en un iframe, por darle un poco de vistosidad al tutorial.

¡Vamos a por el primer paso del tutorial!

Paso 1: La estructura HTML

Como acostumbramos a realizar en nuestros tutoriales, mantendremos una estructura sencilla, intentando que sea vistosa pero sobretodo clara a la hora de comprender qué estamos haciendo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
        <title>Panel lateral desplegable</title>
        <link rel="stylesheet" href="main.css" type="text/css" />
    </head>
    <body>
        <div id="top">
            <h1>
                <a title="Volver a portada" href="/">Google Reader</a>
            </h1>
       </div>
        
        <div id="lateral">
            <h2>Suscripciones</h2>
            <ul id="menu">
                <li>
                    <a href="http://cokidoo.com/">
                        <span class="icon"></span>
                        <span>Cokidoo Labs</span>
                    </a>
                </li>
                <li>
                    <a href="http://web.ontuts.com">
                        <span class="icon"></span>
                        <span>Ontuts</span>
                    </a>
                </li>
                <li>
                    <a href="http://cokisam.com">
                        <span class="icon"></span>
                        <span><strong>Cokisam (2)</strong></span>
                    </a>
                </li>
                <li>
                    <a href="http://erasmusu.com">
                        <span class="icon"></span>
                        <span>Erasmusu</span>
                    </a>
                </li>
            </ul>
        </div>
        
        <div id="content">
            <h2>Inicio</h2>
            <a id="toggler"></a>
            <div id="render">
                <i id="tip">Selecciona uno de los canales a cargar en el listado del panel lateral izquierdo.</i>
                <iframe id="iframe" width="100%" height="100%" src="" frameborder="0"></iframe>
            </div>
        </div>
        
        <div id="footer">
            <span>Tutorial realizado por <a href="http://cokidoo.com">Adrián Mato</a> para <a href="http://web.ontuts.com">Ontuts</a></span>
        </div>

        <!-- scripts -->
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> 
        <script type="text/javascript" src="main.js"></script> 
    </body>
</html>

Sin la hoja de estilo creada, nuestro documento debería mostrarse de la siguiente forma:

Vista previa paso 1

Lo único destacable de este primer paso es comprender que estamos creando la división sin contenido “toggler” que será la que nos permita mostrar / ocultar el panel lateral de id “lateral” mediante el control de los eventos en javascript.

Vamos pues a darle un poco de estilo al ejemplo antes de ponernos con la lógica en javascript…

Paso 2: Aplicando estilo con CSS a nuestro panel lateral

En este caso, el código CSS es muy básico y se centra principalmente en recrear el aspecto visual de la interfaz de Google Reader, es puramente estético, aunque tiene alguna cosa curiosa que comentaremos tras visualizar el código:

/* 
    Document    :   main.css
    Author      :   adrian mato
    Description :   Estilo general
*/

@CHARSET "UTF-8";

/*
    Section    :    CSS RESET
    Description:    Reseteamos practicamente todos los valores de los selectores para facilitar el cross-browsing
*/
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em,
font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody,
tfoot, thead, tr, th, td, button{
    border:0pt none;
    font-family: inherit;
    font-size: 100%;
    font-style: inherit;
    font-weight: inherit;
    margin: 0pt;
    padding: 0pt;
    vertical-align: baseline;
}
body{
    line-height: auto;
    font-size: 12px !Important;
    background: #fff;
    font-family: Helvetica, Arial, sans-serif;
    margin: 0pt;
    cursor: default;
    color: #000;
}
table{
    border-collapse: separate;
    border-spacing: 0pt;
}
strong{
    font-weight: 700;
}
caption, th, td{
    font-weight: normal;
    text-align: left;
}
blockquote:before, blockquote:after, q:before, q:after{
    main: "";
}
blockquote, q{
    quotes: "" "";
}
html,body{
    height: 100%;
    
    overflow: hidden;
}
.clearfix{
    overflow: hidden;
}



/*
    Section    :    TOP
    Description:    Cabecera de nuestro lector RSS
*/
#top{
    height: 40px;
    line-height: 40px;
    padding: 10px 10px 0;
    border-bottom: 1px solid #c9d7f1;
}
#top h1{
    width: 138px;
    height: 30px;
    background: transparent url("img/logo_bg.gif") no-repeat 0 0;
    display: block;
    text-indent: -9999px;
}
#top h1 a{
    display: block;
}

/*
    Section:        LATERAL
    Description:    Panel lateral donde mostramos las distintas fuentes RSS
*/
#lateral{
    width: 260px;
    height: 100%;
    float: left;
}
#lateral h2{
    font-size: 13px;
    font-weight: 700;
    padding: 10px;
}
#lateral ul{
    padding: 10px 0 0;
    list-style: none;
    list-style-position: inside;
}
#lateral li{
    font-size: 13px;
    position: relative;
    line-height: 24px;
}
#lateral li a{
    display: block;
    padding-left: 23px;
    text-decoration: none;
    color: #000;
}
#lateral li.active a, #lateral li.active a:hover{
    background: #c2cff1
}
#lateral li a:hover{
    background-color: #ffffcc;
}
#lateral li a span{
    padding-left: 16px;
}
#lateral li a .icon{
    width: 16px;
    height: 16px;
    position:absolute;
    top: 4px;
    background: transparent url("img/rss_bg.gif") no-repeat left center;
}


/*
    Section:        CONTENT
    Description:    Zona donde cargamos el contenido seleccionado
*/
#content{
    height: 100%;
    margin-left: 260px;
}
#content h2{
    height: 40px;
    line-height: 40px;
    padding: 0 10px 0 20px;
    background: #c2cff1;
    font-size: 18px;
    font-weight: 700;
}
#content #render{
    height: 100%;
    overflow: hidden;
}
#content #tip{
    display: block;
    padding: 20px;
}
#content #iframe{
    display: none;
}


/*
    Section:        TOGGLER
    Description:    Boton que permitirá mostrar / ocultar el panel
*/
#toggler{
    width: 16px;
    height: 100%;
    border-left: 1px solid #c2cff1;
    background: #EBEFF9 url("img/toggler_bg.gif") no-repeat left center;
    float: left;
}
#toggler:hover{
    background: #c2cff1 url("img/toggler_bg.gif") no-repeat -25px center;
    cursor: pointer;
}
#toggler.off{
    background: #EBEFF9 url("img/toggler_off_bg.gif") no-repeat left center;
    margin-left: 0;
}
#toggler.off:hover{
    background: #c2cff1 url("img/toggler_off_bg.gif") no-repeat -25px center;
    margin-left: 0;
}



/*
    Section:        FOOTER
    Description:    Pie de página del panel
*/
#footer{
    width: 100%;
    height: 30px;
    line-height: 30px;
    text-align: right;
    border-top: 1px solid #8c9dc8;
    background: #C2CFF1;
    position: fixed;
    bottom: 0;
}
#footer span{
    padding-right: 10px;
}

Echemos un vistazo a las tres principales divisiones:

  • lateral: división que contiene el listado de elementos seleccionables que permiten cargar las distintas webs a visualizar.
  • content: división que contiene el contenido a cargar y visualizar.
  • toggler: división contenida dentro de “content” y que recibe las acciones de mostrado / ocultado de “lateral”.

Como habréis podido comprobar estamos trabajando siempre con una maquetación líquida, por lo que trataremos siempre de aprovechar el espacio en la ventana de nuestro navegador, no trabajaremos con medidas fijas, salvo el ancho de “toggler”, que me apetece tenerlo fijo.

Una maquetación líquida escapa de tamaños fijos, la forma en la que se muestra el diseño siempre va en relación al tamaño disponible en la ventana.

Las divisiones tratarán siempre de ocupar el 100% del ancho de nuestra ventana de navegador de forma natural, para la altura, le haremos saber que nos interesa que ocupe el 100%, esto no funcionará del todo bien, pero lo ajustaremos mediante javascript en el próximo paso.

Otro detalle interesante es que mediante la clase “off” aplicada a la división “toggler” estaremos alternando el aspecto visual del control de muestreo / ocultado del panel lateral, el cual será mostrado u ocultado mediante código javascript:

Vista previa toggler

Como habréis podido comprobar, la división “lateral” no tiene una clase CSS para controlar su estado, el mostrar o no esta división será sólo cosa del código javascript…

¡Vamos a ello!

Paso 3: Añadiendo interacción con javascript mediante jQuery

Repasemos qué es lo que queremos de nuestro control en forma de panel lateral despegable antes de aplicar la interacción:

  • Mostrar listado de elementos en el panel lateral.
  • Ocultar el panel lateral.
  • Cargar la web de cada elemento seleccionado del panel lateral.

Con esto en mente, necesitaremos identificar mediante selectores de jQuery los distintos elementos que gestionaremos en nuestro código javascript, y posteriormente ir trabajando en toda la funcionalidad anteriormente mencionada.

Antes de entrar en detalle echemos un vistazo al código final:

$(document).ready(function(){
    /*
     * VARIABLES GLOBALES
    */
    //status de panel lateral: 1 ON (default), 0 OFF
    var status = 1;
    //selectores
    var iframe = $("#iframe");
    var tip = $("#tip");
    var title = $("#content h2");
    var toggler = $("#toggler");
    var lateral = $("#lateral");
    var content = $("#content");
    var lateralWidth = lateral.width() + "px";
    //dimensiones disponibles para elementos del panel
    var windowHeight = 0;
    var renderHeight = 0;
    var togglerHeight = 0;
    
    
    /*
     * AL CARGAR EL DOCUMENTO
    */
    calculateDimensions();
    applyDimensions();
    
    
    /*
     * AL CAMBIAR DE TAMAÑO LA VENTANA DEL NAVEGADOR
    */
    $(window).resize(function(){
        calculateDimensions();
        applyDimensions();
    });
    
    
    /*
     * AL HACER CLICK EN TOGGLER (PANEL LATERAL)
    */
    toggler.click(clickToggler);
    
    
    /*
     * AL SELECCIONAR UNO DE LOS ITEMS DEL LISTADO LATERAL
    */   
    $("#lateral a").click(loadItem);


    /*
     * FUNCIONES DE CONTROL DE ELEMENTOS DE INTERFAZ
    */
    // calculo de dimensiones disponibles
    function calculateDimensions(){
        windowHeight = document.documentElement.clientHeight; //alto disponible en ventana del explorador
        renderHeight = (windowHeight - 51 - 40 - 31)  +"px";
        togglerHeight = (windowHeight - 51 - 40 - 31)  +"px";
        /* ¿De donde salen esos valores a restar? Pues de:
         * 51: #top: 40px de height, 10px de padding-top, y 1px de border-bottom
         * 40: #content h2: 40px de height
         * 31: #footer: 30px de height y 1px de border-top
        */
    }
    // aplicado de dimensiones disponibles
    function applyDimensions(){        
        content.css("height", renderHeight);
        toggler.css("height", togglerHeight);
    }
    // control de elemento lateral (toggler)
    function clickToggler(){        
        //ocultamos panel si esta mostrandose
        if(status ==1){
            lateral.hide();
            content.css("margin-left","0px");
            toggler.addClass("off");
            
            status = 0;
        }
        //mostramos panel si esta oculto
        else{
            lateral.show();
            content.css("margin-left", lateralWidth);
            toggler.removeClass("off");
            
            status = 1;
        }
    }
    //control de items a cargar en listado lateral
    function loadItem(e){
        //mostramos iframe y ocultamos consejo (tip)
        iframe.css("display", "block");
        tip.css("display", "none");
        //cargamos en iframe el nuevo sitio seleccionado
        iframe.attr("src", $(e.currentTarget).attr("href"));
        //cancelamos el comportamiento normal, que nos llevaria a la web seleccionada, solo queremos cargarle en el iframe
        title.html("Visualizando » " + $(e.currentTarget).text() + "");
        return false;
    }
});

El código como podéis comprobar es relativamente sencillo, tiene unas cuentas líneas pero casi todas son fáciles de entender, vamos a tratar de visualizarlo en pequeños pasos.

Variables de estado y de selección

Como hemos comentado a lo largo de otros tutoriales de jquery es importante guardar la referencia a los distintos elementos que se utilizarán de forma constante, además de tener alguna variables globales que nos permitan controlar el estado de algunos elementos:

/*
     * VARIABLES GLOBALES
    */
    //status de panel lateral: 1 ON (default), 0 OFF
    var status = 1;
    //selectores
    var iframe = $("#iframe");
    var tip = $("#tip");
    var title = $("#content h2");
    var toggler = $("#toggler");
    var lateral = $("#lateral");
    var content = $("#content");
    var lateralWidth = lateral.width() + "px";
    //dimensiones disponibles para elementos del panel
    var windowHeight = 0;
    var renderHeight = 0;
    var togglerHeight = 0;

El código es bastante claro y legible, así que no vamos a dar más explicación al mismo.

Guardar referencias en variables javascript de los distintos elementos de nuestro documento nos facilitará la vida además de aportar una mayor rapidez de ejecución.

Las variables windowHeight, renderHeight y togglerHeight nos servirán a la hora calcular y aplicar dimensiones a los distintos elementos que forman parte del juego.

Calculando y aplicando dimensiones a nuestro panel lateral

Gestionaremos distintos eventos pero todos ellos terminarán accediendo a dos métodos:

  • calculateDimensions(): calculamos las dimensiones en altura necesarias a aplicar a cada elemento según espacio disponible.
  • applyDimensions(): aplicamos las dimensiones a cada elemento.

Este sería el código de ambas funciones:

// calculo de dimensiones disponibles
    function calculateDimensions(){
        windowHeight = document.documentElement.clientHeight; //alto disponible en ventana del explorador
        renderHeight = (windowHeight - 51 - 40 - 31)  +"px";
        togglerHeight = (windowHeight - 51 - 40 - 31)  +"px";
        /* ¿De donde salen esos valores a restar? Pues de:
         * 51: #top: 40px de height, 10px de margin-top, y 1px de border-bottom
         * 40: #content h2: 40px de height
         * 31: #footer: 30px de height y 1px de border-top
        */
    }
    // aplicado de dimensiones disponibles
    function applyDimensions(){        
        content.css("height", renderHeight);
        toggler.css("height", togglerHeight);
    }

Las dimensiones a nivel de ancho no son un problema, sí lo son a nivel de altura, ya que aunque por CSS especifiquemos claramente que queremos que midan 100%, los anchos, márgenes y otro tipo de propiedades distorsionan y añaden pixels extra a la altura.

Como vemos en la imagen, hay ciertas cantidades fijas a restar a la altura pertenecientes a otras dimensiones y sus propiedades:

cálculo de dimensiones del panel lateral

Una imagen vale más que mil palabras… ¿no? :) . Ahora sólo nos queda afrontar el control de interacción y eventos.

Funcionamiento de la interfaz

Necesitamos dos funciones para controlar el funcionamiento de todo:

  • clickToggler(): Mostrado y ocultado para cuando se pinche en el elemento “toggler”.
  • loadItem(): Carga de la web del elemento seleccionado en la división “content”.

Una vez tenemos estas y otras funciones definidas, sólo queda invocarlas en los eventos correspondientes…

Control de eventos en nuestro panel lateral

En total tenemos cuatro eventos en juego, veamos cuáles son:

  • $(document).ready: al finalizar la carga del documento.
  • $(window).resize: al variar las dimensiones de la ventana del navegador.
  • toggler.click: al hacer click el el botón de mostrado / ocultado de panel lateral.
  • $(“#lateral a”).click: al hacer click en alguno de los elementos del panel lateral.

Aquí tenemos el código javascript:

/*
     * AL CARGAR EL DOCUMENTO
    */
    calculateDimensions();
    applyDimensions();
    
    
    /*
     * AL CAMBIAR DE TAMAÑO LA VENTANA DEL NAVEGADOR
    */
    $(window).resize(function(){
        calculateDimensions();
        applyDimensions();
    });
    
    
    /*
     * AL HACER CLICK EN TOGGLER (PANEL LATERAL)
    */
    toggler.click(clickToggler);
    
    
    /*
     * AL SELECCIONAR UNO DE LOS ITEMS DEL LISTADO LATERAL
    */   
    $("#lateral a").click(loadItem);

Y ya está, hemos terminado con el código javascript. Ya tenemos la estructura html, el estilo y maquetación y el funcionamiento mediante javascript… ¡Sólo queda probarlo!

vista previa de panel lateral en jquery

Reflexión final

Una vez más vuelvo a insistir en lo de siempre: con un poco de curiosidad y ganas por profundizar en lo que nos interesa podemos -en este caso- crear controles dinámicos en javascript de forma realmente sencilla.

Lo más importante es tener claro qué es lo que queremos que haga nuestro control (sus eventos, etc…) y luego buscar la mejor solución posible a cada uno de esos requisitos ya sea con jQuery u otras librerías javascript que manejemos.

Espero que os haya resultado útil y… ¡Nos vemos en el próximo artículo!

¿Necesitas desarrollar un proyecto web o para móviles? ¡Estamos disponibles!

Visitar Cokidoo

Cokidoo, los creadores de Ontuts, desarrollamos proyectos tecnológicos centrados en redes sociales y aplicaciones web, aplicaciones móviles y consultoría web y bases de datos.

Somos jóvenes, inquietos, versátiles, apasionados por la innovación y enfocados en las nuevas tecnologías. Con Ontuts tratamos de compartir nuestro conocimiento adquirido en los distintos proyectos, ayudando a la comunidad y mostrando nuestra capacidad tecnológica.

Si necesitas un presupuesto sin compromiso, estamos disponibles, no dudes en contactar con nosotros.

Comentarios en esta publicación (12 comentarios)

¿Te ha gustado esta publicación? ¡Puedes compartir tu opinión con todos nosotros! Simplemente pincha aquí mismo.

Espero que haya quedado claro, me ha costado bastante explicarme sin que parezca una biblia..

Me gusta mucho lo del mostrar / ocultar el panel lateral

Saludos!

Se ve bien bacán! en realidad yo utilizo dojo pero por cosas de la vida me ha tocado un freelo en el que el cliente me ha pedido que utilice jquery así que este tutorial me viene muy bien para lo que necesitaré

jacinto

Gracias! es un excelente tuto para conocer este tipo de animaciones en JQuery.

Jose Orlando Parra Acosta

En el siguiente link http://www.emenia.es/demos-blog/menu-desplegable2/ encontre este tuto y no se si puede ser adaptado a al panel lateral para poeder tener mas opciones en el menu.
Creando un menú vertical desplegable con jQuery (2)
Tras una pregunta de Saúl sobre el artículo Creando un menú vertical desplegable con jQuery en la que me preguntaba cómo lograr que al abrir una opción del menú se cerrara cualquier otra que estuviera abierta (podéis ver la pregunta en la zona de comentarios del artículo anterior) he actualizado (bueno, básicamente cambiado) el código para que pueda hacerse lo que pide Saúl. Aunque lo he puesto en los comentarios respondiéndole me he animado a crear una nueva entrada por si a alguien le fuera de interés.
Lo que queremos conseguir es esto: Ejemplo de menú vertical desplegable con jQuery con efecto acordeón

Gracias

excelente, lo usaré para mi panel. recien he encontrado este sitio, muy bueno los tutoriales, lo tendré como referencia, gracias y felicitaciones.

Nelson Castañeda

Pregunta: estoy mirando el demos en Windows Seven e internet explorer y mozilla y el aplicativo no se desplaza se queda estatico que puede ser? me pueden ayudar soy nuevo en esto y no se que pueda estar fallando

Junior Bre

Excelente tuto y muy bien explicado, felicidades por el post!!!

Johann Andrés Agámez Ferres

Adrián Mato Muchas gracias por este excelente tutorial por personas como tu es que vale la pena entrar a internet muchas gracias este código lo e buscado por mucho tiempo ya que todos no estaban tan bien explicados como este de nuevo muchas gracias

Tremendo!! eres un AS!!
lo tenia en mente en hacelo pero me han ahorrado un monton de tiempo!!
MILES DE GRACIAS!!

Henry

Esta bien, pero 2 consultas:
1. Como añadir un efecto tipo slideToggle().
2. Si tengo 2 iframes, en el primero se encuentra el menú, en el segundo el contenido. Como seria el código?.