Creando un componente reutilizable con Javascript

Vamos a crear un cronómetro que se pueda reuilizar en cualquier parte de nuestro proyecto como si se tratara de un plugin.

Rodríguez Patiño, Eduardo
2020-09-27 | 6,180 lecturas

En esta entrada vimos como crear un cronómetro con jQuery, ahora vamos a crear el mismo cronómetro sin usar jQuery (si, si, estoy con la filosofía Only JS) y que se pueda reuitilizar en cualqueir parte de nuestro aplicativo.

En estos casos debemos expandir nuestra cerebro y pensar que todo es escalable, TODO. Porque esto va a permitir crear un código más ordenado, que sea más fácil de mantener y hacerlo escalar a un futuro.

CSS

Nuestro CSS debe ser escalable, por lo tanto deberá usar clases en vez de ID y le agregamos un prefijo para que no choque con otra clase que pueda llamarse igual.

.chrono{width:400px;margin:auto;background:#eee;padding:10px;border:1px solid #222;margin-bottom:30px;}
.chrono-container{display:flex;}
.chrono-container div{flex-direction:column;padding:20px;width:100%;text-align:center;font-size:2em;}
.chrono-start{border-radius:2px;padding:10px;display:block;width:100%;font-size:1.4em;border:1px solid #222;background:#222;color:#eee;cursor:pointer;}
.chrono-start:hover{background:#333;color:#eee;}

HTML

La maquetación base es la que mostramos líneas abajo. Cada cronometro le agregamos un contenedor y un ID para que nuestro javascript lo capture y pueda interactuar con este.

<div id="chrono-a" class="chrono">
    <div class="chrono-container">
        <div class="chrono-hour">00</div>
        <div class="chrono-divider">:</div>
        <div class="chrono-minute">00</div>
        <div class="chrono-divider">:</div>
        <div class="chrono-second">00</div>                
    </div>
    <button class="chrono-start">Comenzar</button>
</div>

<div id="chrono-b" class="chrono">
    <div class="chrono-container">
        <div class="chrono-hour">00</div>
        <div class="chrono-divider">:</div>
        <div class="chrono-minute">00</div>
        <div class="chrono-divider">:</div>
        <div class="chrono-second">00</div>                
    </div>
    <button class="chrono-start">Comenzar</button>
</div>

<div id="chrono-c" class="chrono">
    <div class="chrono-container">
        <div class="chrono-hour">00</div>
        <div class="chrono-divider">:</div>
        <div class="chrono-minute">00</div>
        <div class="chrono-divider">:</div>
        <div class="chrono-second">00</div>                
    </div>
    <button class="chrono-start">Comenzar</button>
</div>

<div id="chrono-d" class="chrono">
    <div class="chrono-container">
        <div class="chrono-hour">00</div>
        <div class="chrono-divider">:</div>
        <div class="chrono-minute">00</div>
        <div class="chrono-divider">:</div>
        <div class="chrono-second">00</div>                
    </div>
    <button class="chrono-start">Comenzar</button>
</div>

Javascript

He creado un archivo chrono.js que contiene todo el script para que levante el cronómetro.

var Chrono = function(id){
    var target = {};
    var isRunning = false;
    var timer;    
    var time = {
        hour: 0,
        second: 0,
        minute: 0
    };

    function start(){
        timer = setInterval(function(){
            // seconds
            time.second++;
            if(time.second >= 60)
            {
                time.second = 0;
                time.minute++;
            }      

            // minutes
            if(time.minute >= 60)
            {
                time.minute = 0;
                time.hour++;
            }

            target.hour.innerHTML = time.hour < 10 ? '0' + time.hour : time.hour;
            target.minute.innerHTML = time.minute < 10 ? '0' + time.minute : time.minute;
            target.second.innerHTML = time.second < 10 ? '0' + time.second : time.second;

            console.log('Time elapsed: ' + time.hour + ':' + time.minute + ':' + time.second + ' from ' + id);

            isRunning = true;
        }, 1000);
    }

    function stop()
    {
        isRunning = false;
        clearInterval(timer);
    }

    function init(id){
        target = {
            hour: document.querySelectorAll(id + " .chrono-hour")[0],
            minute: document.querySelectorAll(id + " .chrono-minute")[0],
            second: document.querySelectorAll(id + " .chrono-second")[0],
        };
        
        var _btnStart = document.querySelectorAll(id + " .chrono-start")[0];
        
        _btnStart.addEventListener('click', function(){
            if(!isRunning) {
                _btnStart.innerHTML = 'Detener';
                start();
            }
            else {
                _btnStart.innerHTML = 'Continuar';
                stop();
            }
        })
    }

    init(id);
};
  • Nuestra variable recibe un parámetro, ya que nuestra esta pertenece a una función la cual hemos declarado en el código anterior.
  • Ni bien recibe el parámetro, tenemos una función privada llamada init(id) que se encargará de inicializar el cronometro.
  • Mediante el uso de querySelectorAll identificamos los controles de nuestro cronómetro, donde irá la hora, minuto, segundo y el botón start.
  • A la vez, este método init declara un evento para inicializar o detener el cronómetro cada vez que se haga click.

¿Cómo los inicializo?

Pasandole el ID que contiene a la maquetación del cronómetro.

Chrono('#chrono-a');
Chrono('#chrono-b');
Chrono('#chrono-c');
Chrono('#chrono-d');

Cualquier duda que tengan mi dejan un comentario. Adjunto el código de fuente y el ejemplo online.