El widget Accordion de Spry es sencillo de utilizar y de entender. Sin embargo, intentar convertirlo en dinámico (de forma que se añadan los paneles según los datos) tiene truco.

Un acordeón básico de un solo panel tiene esta estructura:

titulo
texto


El ejemplo anterior funcionará sin problemas, pero: ¿Qué sucede si intentamos aplicarle una región repetida?
[html]
<div class="Accordion" id="Accordion1" spry:region="empleados">
<div class="AccordionPanel" spry:repeat="empleados">
<div class="AccordionPanelTab">{nombre}</div>
<div class="AccordionPanelContent">{datos}</div>
</div>
</div>
<script type="text/javascript">
<!–
var acc = new Spry.Widget.Accordion("Accordion1");
//–>
</script>
[/html]

En este caso, El widget no funcionará. La explicación es sencilla: El widget se crea al mismo tiempo que la región repetida, por lo que aquél es incapaz de controlar todos los paneles que aún no han sido creados. Debemos por tanto encontrar la forma de saber cuándo Spry ha terminado de crear todos los paneles para convertirlos en un acordeón. Para ello tenemos los observers.

Existen elementos de Spry (como las regiones y los datasets) que lanzan notificaciones cuando cambian. Estas notificaciones, similares a los eventos, pueden ser ‘observadas’ por un observer (valga la redundancia), que entrará en funcionamiento cuando se produzca alguna notificación.

En nuestro caso, necesitamos comprobar los cambios en una región, la cual puede realizar las siguientes notificaciones:

  • onLoadingData: La región está cargando los datos desde el dataset
  • onPreUpdate: Los datos se han cargado y la región está a punto de reescribirse con el nuevo html
  • onPostUpdate: La región ya se ha regenerado con el nuevo html y se ha insertado en el documento
  • onError: Ha ocurrido algún error durante el proceso

Por lo tanto, cuando la región envie la notificación onPostUpdate podremos crear el acordeón sin problemas, ya que todo el html ha sido generado.

Aquí entran en juego los observers: Son objetos o funciones (se aceptan ambos y su funcionalidad es similar), que se encargan de vigilar las notificaciónes enviadas por parte de la región y qué hacer cuando eso sucede. Para nuestro ejemplo, utilizaremos un objeto.

Un objeto observer tiene esta estructura:

[js]
//creamos el objeto
var miObserver = new Object;
//le decimos miObserver lo que tiene que hacer cuando recibe un onPostUpdate
//En nuestro caso, debe crear un acordeon
miObserver.onPostUpdate = function()
{
var acc1 = new Spry.Widget.Accordion("Accordion1");
};
//Finalmente, indicamos que miObserver estará pendiente del elemento ‘Accordion1’
Spry.Data.Region.addObserver("Accordion1", miObserver);
[/js]

A partir de ahora,cuando el elemento ‘Accordion1’ se regenere y envie la notificación onPostUpdate, el observer que hemos creado (miObserver) se encargará de crear el acordeon.

El codigo final es:
[html]
<head>
(…)
<script type="text/javascript">
<!–
//creamos el dataset
var empleados = new Spry.Data.XMLDataSet("empleados.xml", "empleados/empleado");
//creamos el observer
var miObserver = new Object;
miObserver.onPostUpdate = function()
{
acc = new Spry.Widget.Accordion("Accordion1");
};
Spry.Data.Region.addObserver("Accordion1", miObserver);
//–>
</script>
(…)
</head>
<body>
<!–Creamos el bloque del futuro acordeon –>
<div class="Accordion" id="Accordion1" spry:region="empleados">
<div class="AccordionPanel" spry:repeat="empleados">
<div class="AccordionPanelTab">{nombre}</div>
<div class="AccordionPanelContent">{datos}</div>
</div>
</div>
</body>
[/html]