miércoles, 21 de julio de 2010

JQuery - Panel colapsable expandible que conserva su estado entre postbacks

Hacer una región colapsable / expandible es una tarea simple... simplemente usas un poco de javascript y a la región que quieres mostrar / ocultar le pones display: none o display:block. Ese es más o menos el resumen.
expand_collapse
expand_collapse_ii
Algunos fanáticos del ajaxcontroltoolkit podrían decir: "pero ya hay un control llamado Accordion que hace eso". Tienes razón, pero particularmente yo prefiero mi propia solución, me parece más limpia... no me genera código por aquí y por allá,  no genera + viewstate, no hay errores típicos y además no sólo funciona para páginas aspx, sino también para html, php, asp, etc.

Y bueno, la principal característica es que conserva su estado entre postbacks, pero además mantiene su estado al regresar desde otra página. Osea, si mi región está colapsado y me voy a otra página, al regresar me mostrará esa región colapsada.
Y cómo hice eso? simple usé cookies, y para no complicarme guardando / recuperando el valor de la cookie, uso un pluggin de JQuery, que ya hace ese trabajo: JQuery.cookie
Para el ejemplo vamos a crear una página expand_collapse.htm y allí ponemos el siguiente código:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Región expandible con jquery</title>
<style type="text/css">
*
{
font-family: Trebuchet MS;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script type="text/javascript" src="js/jquery.cookie.js"></script>
<script type="text/javascript">

$(function () {
var COOKIE_NAME = 'COOKIE_NAME';
var THE_COOKIE = $.cookie(COOKIE_NAME)

if (THE_COOKIE == null || THE_COOKIE == 'max') {
$('#imgExpandCollapse').attr("src", "images/collapse.png");
$.cookie(COOKIE_NAME, 'max', { expires: 7 });
}
else {
$('#imgExpandCollapse').attr("src", "images/expand.png");
$.cookie(COOKIE_NAME, 'min', { expires: 7 });
$('#tbody1').hide();
}

$('#ExpandCollapse').click(function () {
$('#tbody1').toggle();
if (THE_COOKIE == null || THE_COOKIE == 'max') {
$('#imgExpandCollapse').attr("src", "images/expand.png");
$.cookie(COOKIE_NAME, 'min', { expires: 7 });
}
else {
$('#imgExpandCollapse').attr("src", "images/collapse.png");
$.cookie(COOKIE_NAME, 'max', { expires: 7 });
}
THE_COOKIE = $.cookie(COOKIE_NAME);

});
});

</script>
</head>
<body>
<table id="tableForm" style="width: 100%; background-color: orange">
<thead>
<tr>
<th colspan="2" style="vertical-align: top; background-color: black; color: white;
padding-top: 7px; padding-left: 7px">
<div style="float: left; width: 95%; height: 20px">
JQuery - region colapsable que conserva su estado
</div>
<div style="width: 20px; height: 20px; float: right">
<a id="ExpandCollapse" href="javascript:;">
<img id="imgExpandCollapse" src="images/collapse.png" style="border: none;" alt="" />
</a>
</div>
</th>
</tr>
</thead>
<tbody id="tbody1">
<tr>
<td>
<img id="img1" src="http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif"
alt="" />
<p>
Esta es una región expandible hecha con javascript y JQuery ... y que además conserva
su estado entre postbacks...
</p>
</td>
</tr>
</tbody>
</table>
</body>
</html>

Necesitamos también dos imágenes expand.png y collapse.png, las cuales las debes poner dentro de una carpeta llamada images. Además crearemos una carpeta llamada js, donde voy a guardar un archivo javascript llamado jquery.cookie.js y que contiene el sgte código:

/**Cookie plugin
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* @author Klaus Hartl/klaus.hartl@stilbuero.de
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
**/

jQuery.cookie = function(name, value, options) {
if (typeof value != 'undefined') { // name and value given, set cookie
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
var expires = '';
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
var date;
if (typeof options.expires == 'number') {
date = new Date();
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
}
var path = options.path ? '; path=' + (options.path) : '';
var domain = options.domain ? '; domain=' + (options.domain) : '';
var secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
} else { // only name given, get cookie
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
};

Pueden descargar el código original del pluggin jquery desde aquí.

No hay nada que modificar en el archivo jquery.cookie.js simplemente es referenciado desde la página html.

Si analizas un poquito en el código html, verás que en esta parte { expires: 7 } le estoy diciendo que la cookie debe sobrevivir durante 7 días, ósea si no uso la cookie durante más de 7 días: la cookie se borrará.

Espero que les sea de utilidad ;)

1 comentario:

tito herrera dijo...

Muchisimas gracias, es lo que estaba buscando, muy util.

Un saludo.