|

Laboratorio: directorio con búsquedas

Los directorios suelen ser muy útiles para tener organizada la información, pero también puede ser un poco complicado encontrar lo que buscamos si es que existen muchas entradas en el directorio. Por eso, en esta entrada, vamos a explicar cómo añadirle un buscador para que solo nos muestre las entradas que coinciden con un texto (para ser más precisos, con una expresión regular).
listado.png

Esta vez quiero hacerlo usando JSON, normalmente lo hago usando Javascript sencillo porque como no sé si la gente que mira nuestras entradas es entendido o viene buscando a través de Google, pues cuanto más sencillo de entender, mejor, y si luego la persona quiere hacerlo mediante JSON, pues que sepa cómo se hace normalmente. Lo importante es entenderlo, luego si se quiere que se haga un copiar/pegar.

La verdad es que es sencillo, crearemos un objeto mediante JSON, en el cual estarán los datos que queremos mostrar y las funciones que manipulan el “elemento” directorio.

Dentro de los datos tendremos almancenado el título del directorio, el buscador y la lista de entradas de ese directorio, conteniendo a su vez el nombre que muestran, el enlace a la página que representan y unos hijos, que tienen el mismo formato y que pueden no existir (null).

Existen varios métodos: dibujar crea la estructura del directorio y escribe las entradas, insertarDatos es la que se encarga de escribir las entradas (mostrando las que cumplan la expresión regular introducida en el buscador) y luego funciones internas, una para el boton del buscador que muestra la caja de texto y otra que reescribe las entradas dependiendo de lo que se va tecleando en la caja de texto.

Al pulsar sobre la lupa aparecerá una caja de texto en la que al ir introduciendo caracteres, se irá redibujando las entradas, siempre que cada entrada cumpla la expresión regular que se está introduciendo. También se podría hacer cuando se modifica el contenido de la caja, pero de esta otra forma se obtiene un resultado más dinámico.

Los estilos en este caso están optimizados para Firefox, con IE (para variar) obtengo ciertas dificultades, que sinceramente, en este caso, no tengo ganas de solucionar.

El código sería el siguiente:

// feeds consta de:
// titulo : texto de la cabecera
// id : se genera solo
// directorio : información que se quiere monstrar,
//              que se trata de un array de elementos
//    nombre: etiqueta
//    url: enlace
//    hijos: (null | array de elementos iguales)
var feeds = {
"titulo": "Directorio",
"id": null,
"directorio": [
{"nombre": "Blogs", "url": "http://sentidoweb.com/temas/blogs/",
"hijos": [
{"nombre": "Sentido Web", "url": "http://sentidoweb.com/temas/blogs-media/sentido-web/",  "hijos": null},
{"nombre": "Sponsors", "url": "http://sentidoweb.com/temas/blogs-media/sponsors/",  "hijos": null}
]
},
{"nombre": "Blogs Media", "url": "http://sentidoweb.com/temas/blogs-media/",
"hijos": [
{"nombre": "Blogosfera (hisp)", "url": "http://sentidoweb.com/temas/blogs/blogosfera-hisp/",  "hijos": null},
{"nombre": "Blogosfera (int)", "url": "http://sentidoweb.com/temas/blogs/blogosfera-int/",  "hijos": null}
]
},
{"nombre": "CMS", "url": "http://sentidoweb.com/temas/cms/",
"hijos": [
{"nombre": "Blogger", "url": "http://sentidoweb.com/temas/cms/blogger/",  "hijos": null},
{"nombre": "Movable Type", "url": "http://sentidoweb.com/temas/cms/movable-type/",  "hijos": null},
{"nombre": "WordPress", "url": "http://sentidoweb.com/temas/cms/wordpress/",  "hijos": null}
]
},
{"nombre": "Desarrollo Web", "url": "http://sentidoweb.com/temas/desarrollo-web/",
"hijos": [
{"nombre": "AI/Usabilidad", "url": "http://sentidoweb.com/temas/desarrollo-web/aiusabilidad/",  "hijos": null},
{"nombre": "AJAX", "url": "http://sentidoweb.com/temas/desarrollo-web/ajax/",  "hijos": null},
{"nombre": "API", "url": "http://sentidoweb.com/temas/desarrollo-web/api/",  "hijos": null},
{"nombre": "Accesibilidad", "url": "http://sentidoweb.com/temas/desarrollo-web/accesibilidad/",  "hijos": null},
{"nombre": "Apache", "url": "http://sentidoweb.com/temas/desarrollo-web/apache/",  "hijos": null},
{"nombre": "Bases de datos", "url": "http://sentidoweb.com/temas/desarrollo-web/bases-de-datos/",  "hijos": null},
{"nombre": "Comet", "url": "http://sentidoweb.com/temas/desarrollo-web/comet/",  "hijos": null},
{"nombre": "Flash", "url": "http://sentidoweb.com/temas/desarrollo-web/flash/",  "hijos": null},
{"nombre": "Grafismo", "url": "http://sentidoweb.com/temas/desarrollo-web/grafismo/",  "hijos": [
{"nombre": "Blogger", "url": "http://sentidoweb.com/temas/cms/blogger/",  "hijos": null},
{"nombre": "Movable Type", "url": "http://sentidoweb.com/temas/cms/movable-type/",  "hijos": null},
{"nombre": "WordPress", "url": "http://sentidoweb.com/temas/cms/wordpress/",  "hijos": null}
]
},
{"nombre": "Java", "url": "http://sentidoweb.com/temas/desarrollo-web/java/",  "hijos": null},
{"nombre": "Javascript", "url": "http://sentidoweb.com/temas/desarrollo-web/javascript/",  "hijos": null},
{"nombre": "MySQL", "url": "http://sentidoweb.com/temas/desarrollo-web/mysql/",  "hijos": null},
{"nombre": "PHP", "url": "http://sentidoweb.com/temas/desarrollo-web/php/",  "hijos": null},
{"nombre": "Ruby", "url": "http://sentidoweb.com/temas/desarrollo-web/ruby/",  "hijos": null}
]
}
],
// dibuja el elemento directorio
// que contiene el titulo, el buscador
// y el listado
"dibujar" : function(capa) {
// Contenedor de directorio
var contenedor = document.createElement("DIV");
contenedor.className = "listado";
// Contenedor de buscador
var buscador = document.createElement("SPAN");
buscador.style.position = "absolute";
buscador.style.margin = "2px";
buscador.style.width = "200px";
buscador.style.textAlign = "right";
// Caja de texto del buscador
var input = document.createElement("INPUT");
input.style.marginTop = "1px";
input.style.height = "14px";
input.style.width = "150px";
input.style.display = "none";
// Cuando se pulsa una tecla, se vuelve a dibujar el listado
input.onkeyup = function() {
var obj = document.getElementById(feeds.id);
obj.innerHTML = "";
feeds.insertarDatos(feeds.directorio, obj, this.value);
};
input.type = "text";
buscador.appendChild(input);
// La lupa
var buscar = document.createElement("A");
buscar.href = "#";
buscar.onclick = function() {
var obj = this.parentNode.firstChild;
if (obj.style.display == 'inline') {
obj.style.display = 'none';
} else {
obj.style.display = 'inline';
}
}
var lupa = document.createElement("IMG");
lupa.src="lupa.gif";
lupa.border = "0";
lupa.style.marginTop = "2px";
lupa.style.marginLeft = "2px";
buscar.appendChild(lupa);
buscador.appendChild(buscar);
contenedor.appendChild(buscador);
// Contenedor de la cabecera
var cabecera = document.createElement("P");
cabecera.appendChild(document.createTextNode(feeds.titulo));
contenedor.appendChild(cabecera);
// Directorio
var contenedorFeeds = document.createElement("DIV");
contenedorFeeds.id = Math.random();
// Creamos el id para luego poder referenciarlo para redibujar
feeds.id = contenedorFeeds.id;
contenedor.appendChild(contenedorFeeds);
// Rellenamos el listado
feeds.insertarDatos(feeds.directorio, contenedorFeeds);
// Si se especifica capa se añade en esta,
// si no al final del document.body
if (document.getElementById(capa)) {
document.getElementById(capa).appendChild(contenedor);
} else {
document.body.appendChild(contenedor);
}
},
// Escribe el listado según si cada entrada se asemeja al texto
"insertarDatos" : function(obj, capa, texto) {
if (!texto) texto = '';
// Creamos la lista
var ul = document.createElement("UL");
var ultimo = null;
// Por cada objeto del array, miramos si coincide con el texto y lo escribimos
for (var i=0; i<obj.length; i++) {
try { // por si hay error en el expresion regular
// Si tiene hijos, pero no coincide con el texto se procesa porque los hijos si pueden coincidir con el texto
if (texto==null || texto=='' || obj[i].nombre.toLowerCase().match(texto.toLowerCase()) || obj[i].hijos != null) {
// Creamos la entrada con el titulo
var li = document.createElement("LI");
var a = document.createElement("A");
a.href = obj[i].url;
a.appendChild(document.createTextNode(obj[i].nombre));
li.appendChild(a);
ul.appendChild(li);
// si tiene hijos
if (obj[i].hijos) {
// Escribimos los hijos
feeds.insertarDatos(obj[i].hijos, li, texto);
// No se han escrito hijos, se borra el elemento actual
if (texto!='' && !obj[i].nombre.toLowerCase().match(texto.toLowerCase())  &&
li.childNodes[1] && li.childNodes[1].childNodes &&
li.childNodes[1].childNodes.length==0) {
ul.removeChild(li);
}
} else {
// Guardamos el ultimo para darle un estilo especial
ultimo = li;
}
}
} catch (e) {}
}
// El ultimo tiene un estilo especial para que se vea que no quedan más detrás de él
if (ultimo && capa.parentNode && capa.parentNode.tagName == "UL") {
ultimo.className="nodofinal";
}
// Añadimos la lista
capa.appendChild(ul);
}
};
// Carga del directorio
(function() {
var oldOnload = window.onload;
if ('function' == typeof oldOnload) {
window.onload = function() {
oldOnload();
feeds.dibujar();
}
} else {
window.onload = feeds.dibujar;
}
})();

Ejemplo

Código

Similar Posts