Crear un indice de búsqueda por orden alfabético usando Javascript Objects y jQuery.

Escrito por Cesar Cid Robles

3 de julio de 2019

Crear un índice de búsqueda por orden alfabético usando Javascript Objects y jQuery.

Recientemente me tocó desarrollar un índice de búsqueda en mi trabajo como frontend developer. Al disponer de un tiempo limitado para realizar esta tarea, decidí investigar cual era mi mejor alternativa para desarrollar una solución eficaz, debido a que los datos usados para el indice serían actualizados 3 veces por año, no era necesario realizar consultas recurrentes a un endpoint con la información, así que opté por utilizar Javascript Objects para facilitar la carga de los datos y las funciones al mismo tiempo.

Empecé por organizar los datos en un arreglo de Javascript Objects para facilitar la iteración de los mismos. Mis objetos constaban de las siguientes propiedades: SortName, ListingName y GivingLevel.

SortName: Esta propiedad almacenaba en su valor el nombre del donador comenzando por su apellido, con la ayuda de ella podría acomodar los nombres en orden alfabético.

ListingName: Contenía la información del donador empezando por nombre.

GivingLevel: Tenia como valor a que nivel pertenecía cada donador, de acuerdo a la cantidad que habían donado.

Terminamos con un array de objetos como el siguiente:

const donor_info = [
{
SortName: ‘Doe, John’,
ListingName: ‘John Doe’,
GivingLevel: ‘Silver’
}
]

Para habilitar la búsqueda por orden alfabético, crearemos un array que contenga las letras de la A a la Z, todos los apellidos comienzan con letras mayúsculas, entonces solo necesitaremos un array con letras mayúsculas.

const alphabet = [
‘A’,
‘B’,
‘C’,
‘D’,
‘E’,
‘F’,
‘G’,
‘H’,
‘I’,
‘J’,
‘K’,
‘L’,
‘M’,
‘N’,
‘O’,
‘P’,
‘Q’,
‘R’,
‘S’,
‘T’,
‘U’,
‘V’,
‘W’,
‘X’,
‘Y’,
‘Z’
];

Necesitaremos también dos variables auxiliares, una contendrá la letra seleccionada para la búsqueda, la llamaremos currentLetter.

La otra variable va a almacenar la posición en el arreglo de letras que estamos usando y será la que funcione como índice, por obvias razones la llamaremos index.

La interfaz con la que contaremos tendrá los siguientes elementos.

Un abecedario será nuestro principal método de búsqueda de datos, aunque no el único. Al dar click en cada letra, se mostrará la información de los donadores cuyo apellido comience con la letra seleccionada, usaremos una clase chosen para añadir un borde inferior amarillo a la letra seleccionada.

Botones de nivel permitirán renderizar en la pantalla el nivel deseado para cada letra del abecedario, tenemos 4 en total Platinum, Gold, Silver y Bronze usaremos una clase selected para diferenciar el nivel que estamos mostrando en la interfaz de usuario.

Un área destinada a organizar los nombres por nivel, en ella también se mostrará resaltada la letra que estamos consultando. No mostraré ningún dato en este ejemplo, pero la idea es bastante simple.

Como último componente de la interfaz tenemos los botones de navegación, con los cuales podremos desplazarnos un lugar adelante o atrás en el abecedario.

Ahora si, comencemos con la funcionalidad de nuestra página. En la carga inicial del documento, queremos mostrar todos los donadores cuyo apellido comience con la primera letra del abecedario. Para ello usamos jQuery y asignamos una función al método ready de nuestro documento.

//Initial load
$(document).ready(function() {
currentLetter = alphabet[0];
index = 0;
$('#currentLetter').html(currentLetter);
$('#previous-button').attr('disabled', true);
$('#previous-button').addClass('disabled');
renderByLetter(currentLetter);
});

EXPLICACIÓN: La letra actual (currentLetter) es la A, por lo tanto ocupa la posición 0 en nuestro array de letras, la posicion 0 es nuestro indice actual, entonces inicializamos la variable index con un valor de 0. Mostramos la letra actual en nuestra interfaz para hacerla notar al usuario y como obviamente no hay letras antes que la A, desactivamos nuestro botón de navegación Previous/ Anterior.

Para filtrar por niveles usando los botones de la interfaz simplemente ocultaremos los elementos que nos nos interesan de forma sencilla usando el método hide() de jQuery.

//Level buttons functionality
$(‘#button-all’).on(‘click’, function() {
$(‘#platinum’).show();
$(‘#gold’).show();
$(‘#silver’).show();
$(‘#bronze’).show();
});
$(‘#button-platinum’).on(‘click’, function() {
$(‘#platinum’).show();
$(‘#gold’).hide();
$(‘#silver’).hide();
$(‘#bronze’).hide();
});
$(‘#button-gold’).on(‘click’, function() {
$(‘#platinum’).hide();
$(‘#gold’).show();
$(‘#silver’).hide();
$(‘#bronze’).hide();
});
$(‘#button-silver’).on(‘click’, function() {
$(‘#platinum’).hide();
$(‘#gold’).hide();
$(‘#silver’).show();
$(‘#bronze’).hide();
});
$(‘#button-bronze’).on(‘click’, function() {
$(‘#platinum’).hide();
$(‘#gold’).hide();
$(‘#silver’).hide();
$(‘#bronze’).show();
});

La siguiente funcionalidad consiste en alternar las clases para los botones de nivel y para el alfabeto. Esto se logra con métodos muy similares

//Toggle .selected class for level buttons
$(‘#buttons’).on(‘click’, ‘.gift’, function() {
$(‘.gift’).removeClass(‘selected’);//Remove .selected class from all the buttons
$(this).addClass(‘selected’);//Add the .selected class to the clicked button
});

EXPLICACIÓN: El elemento con el ID buttons es un div que contiene los botones con la clase gift, para cada uno de ellos asignaremos una función en su método click, con la cual tomaremos el elemento actual (el botón clickeado) y le asignaremos la clase selected, mientras que con el resto de los botones haremos lo contrario y removemos dicha clase.

Para el alfabeto es básicamente la misma función con unos detalles extra.

//Toggle .chosen class for alphabet letters and updates displayed members and big yellow letter
$(‘#alphabet’).on(‘click’, ‘span’, function() {
var chosenLetter = $(this).html(); //Gets the clicked letter value
index = alphabet.findIndex(letter => letter == chosenLetter);
currentLetter = alphabet[index];
$(‘#currentLetter’).html(currentLetter); //Updates big yellow letter
$(‘span’).removeClass(‘chosen’); //Removes .chosen class from all letters
$(this).addClass(‘chosen’);//Adds .chosen class to clicked letter only
checkIndex(index); //Check the status of the navigation buttons
renderByLetter(currentLetter); //Render the names
});

EXPLICACIÓN: Nuevamente, el elemento con el ID alphabet es el contenedor para todas las letras del abecedario, las cuales están dentro de un span. Usaremos el método findIndex de Javascript para comparar la letra clickeada con cada letra del alfabeto contenido en nuestro array, esto nos dará la posición de dicha letra para actualizar nuestro index y de esta forma asignar un nuevo valor a currentLetter. Con esta información ya podemos volver a pintar nuestra letra actual (letra amarilla en grande) y asignar la clase chosen solo a la letra que fue clickeada. OJO, pudimos haber dado click en la letra Z, lo cual haría imposible volver a dar click en nuestro botón Next / Siguiente, la función checkIndex se encarga de evaluar la posición actual de nuestro índice y activar / desactivar los botones de navegación por nosotros, mostramos dicha función a continuación.

var checkIndex = function(index) {
if (index == 0) { //If letter = A
$(‘#previous-button’).attr(‘disabled’, true); //Disable previous button
$(‘#previous-button’).addClass(‘disabled’);//Disable previous button
}
if (index > 0 && index <= 25) { //If letter is between A and Z
$(‘#previous-button’).attr(‘disabled’, false); //Enable previous button
$(‘#previous-button’).removeClass(‘disabled’);//Enable previous button
$(‘#next-button’).attr(‘disabled’, false); //Enable next button
$(‘#next-button’).removeClass(‘disabled’); //Enable next button
}
if (index == 25) { // If letter = Z
$(‘#next-button’).attr(‘disabled’, true); //Disable next button
$(‘#next-button’).addClass(‘disabled’); //Disable next button
}
};

EXPLICACIÓN: Esta función recibe un parámetro index el cual corresponde con nuestra variable global definida en el método anterior, si la letra es la A, desactivamos el botón Previous/ Anterior, si la letra está entre la A y la Z, activamos ambos botones, por el contrario si la letra es la Z, procederemos a desactivar el botón Next / Siguiente.

Tenemos una función más llamada checkAlphabet, su comportamiento es auto-clickear la letra del alfabeto correspondiente cada que nosotros clickeamos un botón de navegación, ya sea PreviousNext.

Podrás notar algo curioso aquí, el uso de una caracteristica de ECMA Script 6 o ES6, los templates literarios, los cuales nos permiten transformar esto:

var checkAlphabet = function checkAlphabet(letter) {
$(“#”.concat(letter)).click(); //Classic Javscript here!
};

En esto:

var checkAlphabet = function(letter) {
$(`#${letter}`).click(); //Some fancy ES6 template literals here!
};

La funcionalidad de los botones de navegación es muy sencilla de programar con las funciones que ya tenemos disponibles.

Como reto personal, deja en los comentarios del post una explicación de cada función.
//Navigation buttons functionality
$(‘#previous-button’).on(‘click’, function() {
index = index — 1;
currentLetter = alphabet[index];
$(‘#currentLetter’).html(currentLetter);
checkIndex(index);
checkAlphabet(currentLetter);
renderByLetter(currentLetter);
});
$(‘#next-button’).on(‘click’, function() {
index = index + 1;
currentLetter = alphabet[index];
$(‘#currentLetter’).html(currentLetter);
checkIndex(index);
checkAlphabet(currentLetter);
renderByLetter(currentLetter);
});

Usaremos la función allByLetter para obtener todos los nombres que comiencen por la letra especificada.

var allByLetter = function(letter) {
var filteredByLetter = donor_info.filter(
person => person.SortName.charAt(0) == letter
);
return filteredByLetter;
};

La función allByLevel obtiene los nombres de los donadores de acuerdo a su nivel, tomando como referencia la letra actual para solo buscar ese índice en específico

var allByLevel = function(letter, level) {
var filteredByLetter = allByLetter(letter);
var filteredByLevel = filteredByLetter.filter(
person => person.GivingLevel == level
);
return filteredByLevel;
};

Lo siguiente es la función más importante de nuestra página, la que nos va a ayudar a renderizar todos y cada uno de los nombres en nuestra pantalla, esta función se llama renderByLetter y su propósito es mostrar los nombres de la letra que seleccionemos usando los controles que ya programamos anteriormente. Es un poco extensa ya que hace dos cosas a la vez, filtra los datos y los muestra en pantalla, dentro del código hay comentarios explicando cada procedimiento.

var renderByLetter = function(letter) {
var platinum_container = $(‘#platinum-members’); // Container for platinum members
var gold_container = $(‘#gold-members’); // Container for gold members
var silver_container = $(‘#silver-members’); // Container for silver members
var bronze_container = $(‘#bronze-members’); // Container for bronze members
//Clearing containers from any previous data
platinum_container.html(‘’);
gold_container.html(‘’);
silver_container.html(‘’);
bronze_container.html(‘’);
//Fetching levels
var platinum = allByLevel(letter, ‘Platinum’);
var gold = allByLevel(letter, ‘Gold’);
var silver = allByLevel(letter, ‘Silver’);
var bronze = allByLevel(letter, ‘Bronze’);
//Rendering platinum members
platinum.forEach(element => {
var name = $(
‘<div class=”col-12 col-md-4"><p>’ +
element.ListingName+
‘</p></div>’
);
$(‘#platinum-members’).append(name);
});
//Rendering gold members
gold.forEach(element => {
var name = $(
‘<div class=”col-12 col-md-4"><p>’ +
element.ListingName+
‘</p></div>’
);
$(‘#gold-members’).append(name);
});
//Rendering silver members
silver.forEach(element => {
var name = $(
‘<div class=”col-12 col-md-4"><p>’ +
element.ListingName+
‘</p></div>’
);
$(‘#silver-members’).append(name);
});
//Rendering bronze members
bronze.forEach(element => {
var name = $(
‘<div class=”col-12 col-md-4"><p>’ +
element.ListingName +
‘</p></div>’
);
$(‘#bronze-members’).append(name);
});
};

Listo, ahora tienes un buscador indexado que funciona por orden alfabético, pero lo puedes modificar para que funcione con cualquier otro tipo de dato, depende de lo que quieras crear.


Crear un indice de búsqueda por orden alfabético usando Javascript Objects y jQuery. was originally published in 200 Response on Medium, where people are continuing the conversation by highlighting and responding to this story.