martes, 12 de julio de 2011

Mostrar y ocultar gadgets de la sidebar de Blogger

Una pregunta que se repite es ¿cómo hago para que los gadgets de la sidebar del blog, puedan expandirse y contrarerse y de tal modo ganar espacio?

No es algo facil de responder, no porque sea difícil de hacer sino porque hay cientos de variantes; con y sin librerías, con y sin efectos y todas ellas requieren scripts de alguna clase y modificar o adaptar algo de nuestra plantilla; eso es inevitable; si alguien pretende implementar algo similar, deberá hacerlo con cuidado y tratando de entender lo que hace, aunque sea, minimamente.

En Blogger, todos los widgets o gadgets o cómo se los quiera llamar, tienen la misma estructura básica:
<b:widget id='ALGO' locked='false' title='Indice' type='TIPO'>
<b:includable id='main'>
<b:if cond='data:title'>
<h2><data:title/></h2>
</b:if>
<div class='widget-content'>
.......
</div>
</b:includable>
</b:widget>
En ese esquema, H2 es el título y el DIV que está debajo cuya clase es widget-content contiene todo lo demas, sea lo que sea.

Algunos widgets tienen un DIV distinto, con varias clases o con un ID pero para esto, esos detalles carecen de importancia:
<div expr:class='&Mquot;widget-content &quot; + data:display + &quot;-label-widget-content&quot;'>
<div class='widget-content' expr:id='data:widget.instanceId + &quot;_feedItemListDisplay&quot;'>
<div class='widget-content popular-posts'>
La forma básica de crear un sistema que permita permutar entre algo oculto y algo visible es usar un enlace que ejecute una función de tipo toggle; se lee la propiedad display de cierto elemento; si es none (esta oculto) se cambia por block (visible) y si es block se cambia por none. Esto podemos hacerlo con un script sencillo o usar librerías como Scritpaculous o jQuery.

El script sería algo así:
<script type='text/javascript'>
//<![CDATA[
function SINO(cual) {
var elElemento=document.getElementById(cual);
if(elElemento.style.display == 'block') {
elElemento.style.display = 'none';
} else {
elElemento.style.display = 'block';
}
}
//]]>
</script>
Y en el gadget, deberíamos agregar los atributos y eventos:
<h2 onclick='SINO(&quot;permutar&quot;)'><data:title/></h2>

<div class='widget-content' id='permutar' style='display:none;'>
.......
</div>
Se le adosa el evento onclick a la etiqueta H2 (o se agrega un enlace común) y se oculta el DIV que requiere que sea identificado con un ID único; si son varios, cada uno deberá tener un ID diferente.

Pero, JavaScript permite que hagamos lo mismo de modo más automático, para eso están addEventListener y attachEvent que son la forma de agregar esos eventos (onclick por ejemplo) en ciertas etiquetas, sin tener que escribir eso atributos ni agregar IDs. Para eso, siempre necesitamos modificar la plantilla porque, de alguna manera debemos indicarle cuáles son las que queremos manipular. Pero, como queremos que sea algo mucho más genérico, en lugar de usar IDs, usamos clases.

Entonces, en cualquier widget de Blogger:
<h2 class='expcon'><data:title/></h2>
<div class='widget-con'>
..............
</div>
Agregamos la clase expcon a la etiqueta H2 y cambiamos la clase widget-content del DIV por una nueva llamada widget-con.

Si no se quiere hacer esto y se quieren mantener las etiquetas existente (por las dudas) podemos agregar un DIV de este modo:
<h2 class='expcon'><data:title/></h2>
<div class='widget-con'>
<div class='widget-content'>
..............
</div>
</div>
Y ahora, las funciones del script antes de </head>:
<script type='text/javascript'>
//<![CDATA[

// agrega un ID a la etiqueta si se usa Internet Explorer
// http://www.codingforums.com/archive/index.php/t-125144.html
var IEelem={};
function IEaddID(fn,uniqueID) {
return function(event) {return fn.call(IEelem[uniqueID],event);}
}

// esta es la función que agregará el evento onclick
function agregarEVENTO() {
// creo una lista con todas las etiquetas H2
var el = document.getElementsByTagName("h2");
// leo la lista una por una
for (var i=0; i<el.length; i++) {
var c = el[i].className; // leo el contenido del atributo class
// si es una etiqueta H2 con la clase que definí (expcon)
// le agrego un evento que ejecute una función a la que llamo togglewidget
if (c=="expcon") {
if (el[i].addEventListener) {
// Firefox, Chrome, Opera, IE9
el[i].addEventListener("click", togglewidget, false);
} else if (el[i].attachEvent) {
// Internet Explore 8
var uniqueID = el[i].uniqueID;IEelem[uniqueID] = el[i];
el[i].attachEvent("onclick",IEaddID(togglewidget,uniqueID));
}
}
}
}

// y esta es la función que permuta el contenido
function togglewidget() {
// hice click en la etiqueta H2 pero, debo ocultar la etiqueta DIV que es la siguiente; así que la busco
var obj = this.nextElementSibling || this.nextSibling;
// y le invierto la clase
if(obj.className=="widget-con") {
// esta oculta así que la muestro
obj.className = "widget-exp";
} else {
// esta visible así que la oculto
obj.className = "widget-con";
}
}

// una vez que la página web se carga, ejecuto la función
onload=function() { agregarEVENTO(); }

//]]>
</script>
Algo de CSS me permite definir las reglas para esas clases nuevas:
<style>
h2.expcon { cursor: pointer; }
.widget-exp { display: block; }
.widget-con { display: none; }
</style>
De este modo, cada vez que agregue un widget que quiera ocultar y desplegar, sólo deberé cambiar esas dos clases del código que agrega Blogger.

Es verdad que en lugar de cambiar la clase podría cambiar la propiedad display pero, perfiero que quede así ya que esto, me permitirá agregar efectos ... otro dia.

No hay comentarios:

Publicar un comentario