Blogs Media: CSS Mania | VivirLatino | Sentido Web | Apps Mania

Publicidad

Mié27Sep2006

Laboratorio: directorio con búsquedas

19:45 H (CET)| Temas: Javascript · Laboratorio

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

Relacionados

Feedback (2) » Formulario

1. Guillermo ~ Viernes, 08 Dic 2006 | 09:45H:

!Exelente!, pero se podría ir más allá haciendo que los resultados aparecreran dentro de un contenedor al lado del arbol de opciones. Tanto para enlaces internos como externo. El caso es que no se cómo hacerlo

2. Luis ~ Viernes, 08 Dic 2006 | 14:16H:

Hola Guillermo.

No sé si te he entendido del todo, pero creo que esta entrada te podrá ser de utilidad.

Saludos

Conversación

Nombre:

Email:

(no aparecerá)

URL:

(opcional)
¿Recordar datos?

↓ Comentarios (XHTML permitido)