Acordeón multinivel para el listado de artículos
Sigo cambiando cosas que no me gustaban de EggBlog.
El listado de artículos en la columna de la derecha me parecía un poco pobre. Solo mostraba los 10 últimos, por lo que los más antiguos iban quedando relegados al olvido. Se podía acceder a una página con el listado completo de artículos, pero me parecía muy feucha.
La idea era por tanto poder acceder al listado completo de artículos desde cualquier página. Quitar la limitación de 10 artículos es sencillo, pero claro, cuando tenga 100 el listado sería enorme. Hace tiempo trabaje en el curro con un acordeón en Prototype, y me gustaba su funcionalidad, por lo que pensé que sería buena idea tener un acordeón multinivel para los artículos, de forma que se pueda desplegar por años y por meses.
Aquél que usé recuerdo que era un poco “pesado” en cuanto a rendimiento, por lo que decidí usar JQuery en esta ocasión. Buscando un poco encontré este acordeón.
Tenía buena pinta, así que lo estuve probando, y me daba problema al intentar hacerlo multinivel (no realizaba correctamente las animaciones).
Buscando el enlace he encontrado este otro.
También tiene buena pinta, pero no dice nada de multinivel. Tendré que hacer la prueba un día a ver como se comporta.
El caso es que seguí buscando y al final encontré una implementación de un acordeón multinivel que no utiliza ninguna librería por debajo. La implementación es muy simple, el js es diminuto (1,35KB) y funciona a las mil maravillas.
Para implementar el acordeón, el método que hay que modificar es eb_articlelist en el fichero news.php. En principio pensé en adaptar el código existente, pero no me gustaba nada su implementación. Básicamente se hace una consulta SQL para cada mes. Esto puede tener sentido si como máximo se van a mostrar 10 artículos, pero si se quieren mostrar todos no lo veo muy eficiente. Por eso acabé modificando el código por completo:
/**
* Compone un acordeón con todos los artículos publicados, agrupados por meses
* y por años.
* @param integer $n Si su valor es cero no se muestra el acordeón.
*/
function eb_articlelist($n) {
global $lang;
settype( $n, "integer" );
if( $n == 0 ){
return "";
}
$output = '<div class="box"><strong>' . ucwords( $lang['articles'] ) . '</strong>';
$output .= " " . '<ul class="acc acc_sup" id="acc_sup">';
$lastYearShown = 0;
$lastMonthShown = 0;
$query = mysql_query( "SELECT article_id, article_title, article_date"
." FROM eb_articles WHERE article_flag != 0"
." ORDER BY article_date DESC" );
$countNestedAcc = 0;
while( $row = mysql_fetch_array( $query ) ) {
$articleDate = $row['article_date'];
$currentArticleYear = date( "Y", $articleDate );
$currentArticleMonth = date( "n", $articleDate );
if( $currentArticleYear != $lastYearShown ) {
if( $lastYearShown != 0 ) {
// Cerramos el año anterior
$output .= '</ul></div></div></li>';
}
// Abrimos el nuevo año
$output .= " " . '<li><h3>' . $currentArticleYear . '</h3>'
." " . '<div class="acc-section"><div class="acc-content">'
." " . '<ul class="acc nested" id="nested_'.$countNestedAcc.'">';
$countNestedAcc++;
$lastYearShown = $currentArticleYear;
}
if( $currentArticleMonth != $lastMonthShown ) {
if( $lastMonthShown != 0 ) {
// Cerramos el mes anterior
$output .= " " . '</ul></div></div></li>';
}
// Abrimos el nuevo mes
$output .= " " . '<li><h3>' . ucwords( $lang['month' . $currentArticleMonth] )
. " " . $currentArticleYear . '</h3>'
. " " . '<div class="acc-section"><div class="acc-content"><ul>';
$lastMonthShown = $currentArticleMonth;
}
$output .= " " . '<li><a href="'
.eb_links_article( $row['article_title'], $row['article_id'] ) . '">'
.$row[1] . '</a></li>';
}
// Cerramos el último mes, año y acordeon
$output .= " " . '</ul></div></div></li>'
." " . '</ul></div></div></li>'
." " . '</ul>';
// Inicializamos los acordeones con javascript
$output .= " ".'<script type="text/javascript" src="_lib/scripts/script.js"></script>'
." " . '<script type="text/javascript">';
// Acordeón superior
$output.=" ".'var parentAccordion = new TINY.accordion.slider( "parentAccordion" );'
." " . 'parentAccordion.init( "acc_sup", "h3", 0, 0);';
// Acordeones anidados
for( $i = 0; $i < $countNestedAcc; $i++ ) {
if( $i == 0 ) {
$ex = 0;
}
else{
$ex = -1;
}
$output .= " " . 'var nestedAcc' . $i . '=new TINY.accordion.slider( "nestedAcc' . $i . '" );'
." " . 'nestedAcc' . $i . ' . init( "nested_' . $i . '", "h3", 1,' . $ex . ', "acc-selected" );';
}
// Fin del script
$output .= " " . '</script>';
// Fin del div box
$output .= '</div>';
return $output;
}
Colocamos el script del acordeón (script.js) en la carpeta _lib/scripts, y añadimos las imágenes a themes/default/images.
Por último hay que modificar los estilos para el acordeón, por lo que añadimos los siguientes estilos a style.css:
/* ESTILOS PARA EL ACORDEÓN */
.acc_sup {
width:205px;
list-style:none;
color:#033;
margin:0 auto 40px -16px;
}
.acc_sup h3 {
width:165px;
border:1px solid #9ac1c9;
padding:6px 6px 8px;
font-weight:bold;
margin-top:5px;
cursor:pointer;
background:url(images/header.gif);
font-size: 9pt;
margin: 0;
}
.acc_sup h3:hover { background:url( images/header_over.gif ) }
.acc_sup .acc-section {
overflow:hidden;
background:#fff;
width: 180px;
}
.acc_sup .acc-content {
width:162px;
padding:15px;
border:1px solid #9ac1c9;
border-top:none;
background:#fff;
padding-left: 0px;
}
.nested {
width:180px;
list-style:none;
color:#033;
margin-bottom:15px;
margin-left: -7px;
}
.nested h3 {
width:145px;
border:1px solid #9ac1c9;
padding:6px 6px 8px;
font-weight:bold;
margin-top:5px;
cursor:pointer;
background:url(images/header.gif);
}
.nested h3:hover { background:url( images/header_over.gif ) }
.nested .acc-section {
overflow:hidden;
background:#fff;
width: 160px;
}
.nested .acc-content {
width:127px;
padding:15px;
border:1px solid #9ac1c9;
border-top:none;
background:#fff;
}
.nested .acc-selected { background:url( images/header_over.gif ) }
Con esto me cargo la página con el listado de artículos. Total, ya no aporta ninguna funcionalidad, y para mostrar el mismo acordeón que en el resto de las páginas, ya no tenía mucho sentido 😀