Adición de alarmas al reloj digital

La semana pasada, creamos un reloj digital alimentado por jQuery y CSS3. En esta actualización, agregaremos soporte para configurar alarmas usando el elemento de audio HTML5.

La idea

Para extender el reloj digital con soporte para alarmas, necesitamos agregar algunas funciones cruciales al código de la semana pasada:

  • Necesitamos tener una forma para que las personas establezcan y editen alarmas. Esto requeriría algún tipo de diálogo con campos para configurar la hora de la alarma;
  • Cada segundo, tendremos que comprobar si debe sonar una alarma. Si es así, reproduciremos un pequeño archivo de audio y mostraremos un cuadro de diálogo "Se acabó el tiempo".

Estas características requerirán cambios en HTML, CSS y jQuery. ¡Comencemos!

El HTML

Tendremos dos cuadros de diálogo:uno para configurar/editar una alarma y otro que se muestra cuando suena una alarma.

index.html

<div class="overlay">

    <div id="alarm-dialog">

        <h2>Set alarm after</h2>

        <label class="hours">
            Hours
            <input type="number" value="0" min="0" />
        </label>

        <label class="minutes">
            Minutes
            <input type="number" value="0" min="0" />
        </label>

        <label class="seconds">
            Seconds
            <input type="number" value="0" min="0" />
        </label>

        <div class="button-holder">
            <a id="alarm-set" class="button blue">Set</a>
            <a id="alarm-clear" class="button red">Clear</a>
        </div>

        <a class="close"></a>

    </div>

</div>

<div class="overlay">

    <div id="time-is-up">

        <h2>Time's up!</h2>

        <div class="button-holder">
            <a class="button blue">Close</a>
        </div>

    </div>

</div>

Ambos cuadros de diálogo están ocultos con CSS y se muestran con el método jQuery fadeIn() cuando se necesitan. Otra cosa que vale la pena señalar es que el cuadro de diálogo de alarma usa el número de HTML5 tipos de entrada con un min valor de 0. Las entradas de números son muy fáciles de validar con JavaScript (más sobre eso en la siguiente sección) y también muestran el teclado numérico en los dispositivos móviles.

El siguiente es el elemento de audio HTML5. Contiene etiquetas de origen con dos formatos de audio diferentes. El primero es una versión mp3 del sonido de la alarma, y ​​el segundo ogg. El formato ogg solo es necesario en Firefox, que aún no admite la reproducción de mp3 debido a problemas de licencia. Casi todos los demás navegadores que admiten audio HTML5 también admiten mp3.

index.html

<audio id="alarm-ring" preload>
    <source src="assets/audio/ticktac.mp3" type="audio/mpeg" />
    <source src="assets/audio/ticktac.ogg" type="audio/ogg" />
</audio>

El atributo de precarga le dice al navegador que estos archivos de sonido deben descargarse con anticipación, lo que hará que estén disponibles de inmediato una vez que decidamos reproducirlos (de lo contrario, habría un retraso desde la primera vez que se reproduce una alarma hasta que se descargan). Reproducir el archivo de audio es extremadamente simple gracias a la API de audio HTML5 de JavaScript (más sobre eso en el siguiente fragmento).

JQuery

En esta sección del tutorial, extenderemos el código jQuery del reloj digital para admitir y reproducir las alarmas. No explicaré el código que escribimos la última vez, solo las nuevas incorporaciones.

Lo primero que tenemos que hacer es definir una serie de variables, importantes para el funcionamiento de las alarmas:

activos/js/script.js

var dialog = $('#alarm-dialog').parent(),
    alarm_set = $('#alarm-set'),
    alarm_clear = $('#alarm-clear'),
    time_is_up = $('#time-is-up').parent();

// This will hold the number of seconds left
// until the alarm should go off
var alarm_counter = -1;

A continuación, tenemos que comprobar si hay una alarma pendiente en cada tic del update_time() función.

// Is there an alarm set?

if(alarm_counter > 0){

    // Decrement the counter with one second
    alarm_counter--;

    // Activate the alarm icon
    alarm.addClass('active');
}
else if(alarm_counter == 0){

    time_is_up.fadeIn();

    // Play the alarm sound. This will fail
    // in browsers which don't support HTML5 audio

    try{
        $('#alarm-ring')[0].play();
    }
    catch(e){}

    alarm_counter--;
    alarm.removeClass('active');
}
else{
    // The alarm has been cleared
    alarm.removeClass('active');
}

Cuando el contador llegue a 0, esto significaría que deberíamos reproducir el sonido de la alarma y mostrar el cuadro de diálogo "Se acabó el tiempo". Tenga en cuenta que aunque estoy seleccionando el #alarm-ring elemento de audio con jQuery, estoy accediendo al primer elemento DOM dentro de la colección, así que tengo acceso a JavaScript play() método que está disponible en elementos de audio.

Lo último que queda por hacer es manejar el cuadro de diálogo "Establecer una alarma" y los distintos botones:

// Handle setting and clearing alamrs

$('.alarm-button').click(function(){

    // Show the dialog
    dialog.trigger('show');

});

dialog.find('.close').click(function(){
    dialog.trigger('hide')
});

dialog.click(function(e){

    // When the overlay is clicked, 
    // hide the dialog.

    if($(e.target).is('.overlay')){
        // This check is need to prevent
        // bubbled up events from hiding the dialog
        dialog.trigger('hide');
    }
});

alarm_set.click(function(){

    var valid = true, after = 0,
        to_seconds = [3600, 60, 1];

    dialog.find('input').each(function(i){

        // Using the validity property in HTML5-enabled browsers:

        if(this.validity && !this.validity.valid){

            // The input field contains something other than a digit,
            // or a number less than the min value

            valid = false;
            this.focus();

            return false;
        }

        after += to_seconds[i] * parseInt(parseInt(this.value));
    });

    if(!valid){
        alert('Please enter a valid number!');
        return;
    }

    if(after < 1){
        alert('Please choose a time in the future!');
        return; 
    }

    alarm_counter = after;
    dialog.trigger('hide');
});

alarm_clear.click(function(){
    alarm_counter = -1;

    dialog.trigger('hide');
});

// Custom events to keep the code clean
dialog.on('hide',function(){

    dialog.fadeOut();

}).on('show',function(){

    // Calculate how much time is left for the alarm to go off.

    var hours = 0, minutes = 0, seconds = 0, tmp = 0;

    if(alarm_counter > 0){

        // There is an alarm set, calculate the remaining time

        tmp = alarm_counter;

        hours = Math.floor(tmp/3600);
        tmp = tmp%3600;

        minutes = Math.floor(tmp/60);
        tmp = tmp%60;

        seconds = tmp;
    }

    // Update the input fields
    dialog.find('input').eq(0).val(hours).end().eq(1).val(minutes).end().eq(2).val(seconds);

    dialog.fadeIn();

});

time_is_up.click(function(){
    time_is_up.fadeOut();
});

Hay algunas cosas interesantes sobre este código. Observe cómo estoy usando el validity incorporado property en la línea 35, que existe para el tipo de entrada de número en los navegadores modernos. Nos dice si el contenido del campo de entrada es un número mayor que 0 (recordemos que tienen un valor mínimo de 0).

Otra cosa que vale la pena señalar es la forma en que se organiza el código para el cuadro de diálogo de alarma con eventos personalizados. Cuando el show se activa el evento, calculamos las horas, minutos y segundos restantes de la alarma, que luego se insertan en los campos de entrada.

¡Con esto nuestro bonito reloj digital con alarmas está listo! Espero que te haya gustado este rápido tutorial y que lo encuentres útil en tus propios proyectos.


No