Mini-sistema de ayuda con jQuery

En este tutorial, vamos a crear un mini-sistema de ayuda con jQuery. Se tratará de un pequeño widget que mostrará un texto de ayuda o una guía para los usuarios de la aplicación web. En el contenido del widget se van a poder realizar búsquedas en tiempo real, y resaltaremos todos los términos coincidentes.

La idea

Para desarrollar el mini-sistema de ayuda, esto es lo que tendremos que hacer:

Tenemos que detectar el evento input en el cuadro de texto. Personalmente prefiero esto a keypress, input es capaz de detectar otros eventos como cortar/pegar y deshacer/rehacer. No es compatible con navegadores antiguos (<IE9), aunque, si así lo deseas, puedes sustituirlo por keypress para que el ejemplo funcione en dichos navegadores.
Vamos a desarrollar un plugin de jQuery, al cual llamaremos "highlight", que reemplazará al texto que coincide con los elementos span. Utilizaremos el plugin jQuery.scrollTo para desplazarnos sin problemas por los elementos span en la vista.

Vamos a empezar con la plantilla.

El HTML

El primer paso es establecer el código HTML de la página en la que vamos a trabajar:

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Mini Help System with jQuery </title>

        <!-- Our stylesheet -->
        <link rel="stylesheet" href="assets/css/styles.css" />

    </head>
    <body>

        <div id="widget">

            <div id="header">
                <input type="text" id="search" placeholder="Search in the text" />
            </div>

            <div id="content">
                <!-- Your help text goes here -->
            </div>
        </div>​​

        <!-- JavaScript Includes -->
        <script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
        <script src="assets/js/highlight.jquery.js"></script>
        <script src="assets/js/jquery.scrollTo.min.js"></script>
        <script src="assets/js/script.js"></script>
    </body>
</html>

Como ves, nada fuera de lo normal. Hemos incluido la hoja de estilo en el head (de la cual, debido a su baja importancia no hablaremos en este tutorial). Antes de cerrar el body también incluimos la librería jQuery y el plugin scrollTo, junto a dos archivos js más de los que discutiremos en la siguiente sección. El widget contiene un campo de texto (dentro del div #header) y un #content. Dentro de este último, pondremos la guía de ayuda para tu aplicación.

El código jQuery

Ahora vamos a desarrollar un plugin de jQuery que busque palabras específicas en el elemento #content, y reemplace las coincidencias por elementos span. Por ejemplo, si buscamos la palabra “javascript” en el texto “javascript is awesome” derivará en:

<span class="match">javascript</span> is awesome

Más adelante daremos estilo al span .match con un fondo de color naranja que le haga ser fácilmente reconocible.

El plugin cuenta con dos argumentos: un término de búsqueda (un string), y una función de devolución de llamada opcional que se ejecutará cuando el proceso de búsqueda/reemplazo se haya completado. Como se verás más adelante, utilizaremos la devolución de llamada para asignar el plugin scrollTo y hacer scroll por el div #content para desvelar las coincidencias.

Antes de empezar a leer este código, ten en cuenta que no se puede simplemente buscar el código HTML interno del div, y llamar a replace() para reemplazar las coincidencias de búsqueda por elementos span, ya que de esta manera chafarías el diseño. Si alguien introduce "div" como término de búsqueda, se formaría un caos, ya que derivaría en...

<<span class="match">div</span>>

...lo que estropería TOOODA nuestra plantilla.

La solución a esto es un poco más compleja (pero no difícil una vez que se entiende la idea). Vamos a utilizar el método de jQuery contents() para recuperar todos los hijos del elemento, y haremos replace() solo del texto de los nodos de texto (que no contienen html). A continuación, recorreremos todos los nodos sin texto de los hijos del elemento de forma recursiva, y repetiremos los pasos.

assets/js/highlight.jquery.js

(function($) {

    var termPattern;

    $.fn.highlight = function(term, callback) {

        return this.each(function() {

            var elem = $(this);

            if (!elem.data('highlight-original')) {

                // Save the original element content
                elem.data('highlight-original', elem.html());

            } else {

                // restore the original content
                elem.highlightRestore();

            }

            termPattern = new RegExp('(' + term + ')', 'ig');

            // Search the element's contents
            walk(elem);

            // Trigger the callback
            callback && callback(elem.find('.match'));

        });
    };

    $.fn.highlightRestore = function() {

        return this.each(function() {
            var elem = $(this);
            elem.html(elem.data('highlight-original'));
        });

    };

    function walk(elem) {

        elem.contents().each(function() {

            if (this.nodeType == 3) { // text node

                if (termPattern.test(this.nodeValue)) {
                    // wrap the match in a span:
                    $(this).replaceWith(this.nodeValue.replace(termPattern, '<span class="match">$1</span>'));
                }
            } else {
                // recursively call the function on this element
                walk($(this));
            }
        });
    }

})(jQuery);

Y voilá, nuestro texto está lleno de bonitos highlights. No te preocupe si no has entendido muy bien cómo funciona esto ya que se ha empaquetado como un plugin de jQuery fácil de utilizar, y puedes utilizarlo en tu proyecto de manera sencilla.

Así se tendría que utilizar el plugin:

assets/js/script.js

$(function() {

    var search = $('#search'),
        content = $('#content'),
        matches = $(), index = 0;

    // Listen for the text input event
    search.on('input', function(e) {

        // Only search for strings 2 characters or more
        if (search.val().length >= 2) {

            // Use the highlight plugin
            content.highlight(search.val(), function(found) {

                matches = found;

                if(matches.length && content.is(':not(:animated)')){
                    scroll(0);
                }

            });
        } else {
            content.highlightRestore();
        }

    });

    search.on('keypress', function(e) {

        if(e.keyCode == 13){ // The enter key
            scrollNext();
        }

    });

    function scroll(i){
        index = i;

        // Trigger the scrollTo plugin. Limit it
        // to the y axis (vertical scroll only)
        content.scrollTo(matches.eq(i), 800, { axis:'y' } );
    }

    function scrollNext(){
        matches.length && scroll( (index + 1) % matches.length );
    }
});

En la devolución de llamada, disparamos la función scroll(0). Esto anima al div #content para que muestre la primera coincidencia de la serie. Hay otra función para el scroll, scrollNext, a la cual se le llama cuando pulsamos la tecla return mientras se escribe.

¡Con este nuestro mini sistema de ayuda está completo!

Fuente: tutorialzine.com

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP