viernes, 13 de junio de 2014

Html5 JavaScript Apis

Hola amigos, hace algunos días, para ser más exacto el pasado 31 de mayo de 2014, estuve dictando una charla en el Html Day Medellín, en donde tuve la oportunidad de compartir acerca de las Apis JavaScript que nos ofrece Html5. Y cómo suelo hacer después de cada charla comparto la presentación y la demo que realizo. Y bueno esta no será la excepción, es por esto que voy a dar una breve introducción y vamos a implementar algunos ejemplos con algunas de las apis de JavaScript que tenemos con Html5. Para empezar en un artículo anterior les compartí la presentación de mi charla, y ahora vamos a ver las demos de las Apis que se detallan en ella.

Introducción

Son una serie de funcionalidades JavaScript que nos permiten realizar diferentes operaciones de forma nativa, sin necesidad de referenciar en nuestras aplicaciones librerías externas, como por ejemplo lograr Drag & Drop en nuestro controles Html, sin necesidad de referenciar un plugin de Jquery u otro Framework para lograrlo.

Ahora observemos en detalle algunas de estas Apis:

Geolocation:

Este Api nos permite obtener la ubicación geográfica actual de nuestro usuario, en coordenadas de latitud y longitud, ya que esta acción tiene incidencia en la privacidad del usuario, se requiere de su autorización para lograr obtener esta información.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Geolocation Html5 Api</title>
    <script>
    function ObtenerUbicacion() {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(MostrarCoordenadas);
        } else {
            document.getElementById("divCoordenadas").innerHTML = "Actualiza tu browser, no soporta geolocalización.";
        }
    }
 
    function MostrarCoordenadas(posicion) {
        document.getElementById("divCoordenadas").innerHTML = "Latitud: " + posicion.coords.latitude + "\t Longitud: " + posicion.coords.longitude;
    }
    </script>
</head>
<body>
    <div id="divCoordenadas"></div>
    <script>
        ObtenerUbicacion();
    </script>
</body>
</html>

Como vemos en el Demo anterior es bastante sencillo usar este Api de Geolocalización, en cual obtenemos la ubicación del usuario y la mostramos en un Div, como podemos ver en el método ObtenerUbicaicon usamos el Api navigator.geolocation, para validar en primera instancia si el navegador del usuario soporta esta característica (Esta validación se las recomiendo siempre para cualquier Api de html5), y como vemos a través del método getCurrentPosition especificamos el método o función en el cual vamos a recibir las coordenadas en su único parámetro, en nuestro caso es el método MostrarCoordenadas y para finalizar obtenemos el parámetro posición del cual accedemos a sus propiedades coords.Longitude o latitude respectivamente, para al final mostrar las coordenadas.

Drag & Drop

Este Api nos permite habilitar determinados controles para que puedan ser arrastrados y ubicados en otro lugar, en Html5 cualquier elemento puede ser dragable.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Drag & Drop Demo</title>
    <script>
        function drag(event) {
            event.dataTransfer.setData("Text", event.target.id);
        }
 
        function PermitirDrop(event) {
            event.preventDefault();
        }
 
        function drop(event) {
            event.preventDefault();
            var idObjeto = event.dataTransfer.getData("Text");
            event.target.appendChild(document.getElementById(idObjeto));
        }
 
    </script>
</head>
    <body>
        <div id="divIzquierda" ondragover="PermitirDrop(event)" ondrop="drop(event)" style="background-colorbluewidth50pxheight50px;"></div>
        <div id="divCentro" draggable="true" ondragstart="drag(event)" style="background-colorredwidth30pxheight30px;"></div>
        <div id="divDerecha" ondragover="PermitirDrop(event)" ondrop="drop(event)" style="background-colordarkkhakiwidth50pxheight50px;"></div>
    </body>
</html>

En la demo anterior vemos tres div, uno de color azul, otro de color dorado y otro de color rojo, en este demo se logra que el Div de color rojo pueda ser arrastrado y soltado en alguno de los otros dos Div. Observemos que de igual forma su implementación es bastante sencilla, y debemos manejar varios aspectos clave:
  • draggable = "true": como vemos el Div de color rojo, tiene este atributo en true, lo cual lo habilita para que el usuario lo pueda arrastrar
  • OnDragStart Event: es esencial manejar este evento, ya que se ejecuta cuando el usuario hace clic sobre el control y lo empieza a arrastrar. Si observamos la demo, el Div rojo es quien maneja este evento, ya que es el único dragable, y si vemos la implementación del evento simplemente establecemos en el DataTransfer un dato de tipo texto(Text) en el cual almacenamos el id del Div rojo en este caso. Esto para saber en los siguientes eventos cual fue el control que arrastró el usuario.
  • OnDragOver Event: Este evento se maneja para implementar alguna funcionalidad justo cuando el usuario arrastra el control y esta sobre el control destino, pero aún no lo ha soltado.
  • OnDrop Event: Este evento se ejecuta cuando el usuario suelta el control que arrastró sobre el control destino, y es aquí donde debemos recuperar el id del control almacenado en el DataTransfer para agregarlo en el control destino, tal y como se ve en la función drop de la demo anterior.
Web Storage

Este Api nos permite almacenar información en el browser del usuario, mucho más rápido que las cookies. Permite almacenar grandes cantidades de información sin afectar el performance del sitio web. Su almacenamiento se hace en Key / Value pairs.

Existen dos tipos de almacenamiento:
  • localStorage: Su durabilidad no tiene fecha de expiración.
  • SessionStorage: La información se pierde una vez se cierra el browser.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Web Storage Demo</title>
    <script>
        function AlmacenarLocalStorage(nombre) {
            if (typeof(Storage) !== "undefined") {
                localStorage.Nombre = nombre;
            }
            else {
                document.getElementById("localStorage").innerHTML = "Su navegador no soporta web storage.";
            }
        }
 
        function ObtenerLocalStorage() {
            document.getElementById("localStorage").innerHTML = localStorage.Nombre;
            // localStorage.removeItem("Nombre");
        }
        
        function AlmacenarSessionStorage(apellido) {
            if (typeof (Storage) !== "undefined") {
                sessionStorage.Apellido = apellido;
            }
            else {
                document.getElementById("SessionStorage").innerHTML = "Su navegador no soporta web storage.";
            }
        }
 
        function ObtenerSessionStorage() {
            document.getElementById("SessionStorage").innerHTML = sessionStorage.Apellido;
        }
 
    </script>
</head>
    <body>
        <h2>Local Storage</h2>
        <form>
            <input type="text" id="txtNombre"/>
            <input type="button" id="btnAlmacenar" value="Almacenar en Local Storage" onclick="AlmacenarLocalStorage(document.getElementById('txtNombre').value);" />
            <button id="btnSubmit">Generar Submit</button>
            <input type="button" id="btnObtener" value="Recuperar Local Storage" onclick="ObtenerLocalStorage();"/>
            <a href="PersistenciaWebStorageDemo.html">Ir a Drag & Drop Demo</a>
            <div id="localStorage"></div>
        </form>
        
        <h2>Session Storage</h2>
        <form>
            <input type="text" id="txtApellido" />
            <input type="button" id="btnAlmacenar2" value="Almacenar en Session Storage" onclick="AlmacenarSessionStorage(document.getElementById('txtApellido').value);" />
            <button id="btnSubmit2">Generar Submit</button>
            <input type="button" id="btnObtener2" value="Recuperar Session Storage" onclick="ObtenerSessionStorage();" />
            <a href="PersistenciaWebStorageDemo.html">Ir a Drag & Drop Demo</a>
            <div id="SessionStorage"></div>
        </form>
 
    </body>
</html>

Cómo vemos en el demo anterior implementamos un ejemplo para cada tipo de almacenamiento, que de hecho se manejan de la misma forma, la única diferencia como vimos es la durabilidad de los datos en el browser del usuario. Y la clave del trabajo con el web storage es el manejo de LocalStorage y SessionStorage para obtener y crear propiedades, adicional podemos observar los datos almacenados en el navegador a través de las herramientas de desarrollo, y debemos tener en cuenta que los datos almacenados persisten entre los llamados a diferentes páginas.


Web Workers

Este Api nos permite ejecutar tareas en segundo plano, para evitar bloquear la interacción del usuario con el sistema, y que este pueda seguir normalmente mientras ejecutamos otro tipo de tareas.


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Html5 Web Workers Demo</title>
    <script>
 
        function EjecutarWorker() {
            if (typeof (workerTask) == "undefined") {
                workerTask = new Worker("AdministrarContador.js");
            }
 
            workerTask.onmessage = function (event) {
                document.getElementById("contador").innerHTML = event.data;
            };
        }
    </script>
</head>
<body>
    <div id="contador"></div>
    <script>
        EjecutarWorker();
    </script>
    <input type="button" value="Detener Contador" onclick="workerTask.terminate();">
</body>
</html>

Con los WebWorkers trabajamos con la clase Woeker y con un archivo JS externo, en el cual implementamos el proceso que deseamos ejecutar en segundo plano, si observamos en este caso usamos el JS AdministrarContador.js en el cual realizamos el siguiente proceso:

var contador = 0;
function AumentarContador() {
    contador++;
    postMessage(contador);
    setTimeout("AumentarContador()", 1000);
}
 
AumentarContador();

Cómo vemos es simplemente una función recursiva que aumenta un contador, y a través del método postMessage enviamos una actualización al Worker. Y en la función onmessage que delegamos al worker recibimos esa actualización enviada desde el archivo JS (AdministrarContador.js).

Server Sent

Este Api nos permite recibir actualizaciones automáticamente por parte de código escrito de lado del servidor


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script>
        function ActualizarDesdeServidor() {
            if (typeof (EventSource) !== "undefined") {
                var source = new EventSource("ServerSentDemo.aspx");
                source.onmessage = function (event) {
                    document.getElementById("result").innerHTML += event.data + "<br>";
                };
            }
            else {
                alert('Su navegador no soporta Server Sent');
            }
        }
    </script>
</head>
<body>
    <div id="result"></div>
    <script>
        ActualizarDesdeServidor();
    </script>
</body>
</html>

Cómo vemos usamos el objeto EventSource para especificar el archivo de código de servidor que enviará las actualizaciones, y manejamos el evento onmessage al igual que en los WebWorkers para recibir las actualizaciones, bastante simple. Y veamos por ejemplo cómo trabajaríamos del lado del servidor con Asp.Net:

        protected void Page_Load(object sender, EventArgs e)
        {
            Response.ContentType = "text/event-stream";
            Response.Expires = -1;
            Response.Write(string.Format("data: hora del servidor: {0}"DateTime.Now));
            Response.Flush();
        }

Importante el ContentType, en el cual especificamos event-stream para lograr las actualizaciones en tiempo real, y en este caso enviamos actualizaciones de la fecha y hora del servidor a nuestro cliente a través del Response.Write.

Bueno amigos eso es todo de esta muestra de cómo usar las Apis JavaScript de Html5, espero les sea de utilidad y de interés. Y no duden en compartirlo.

Saludos, y buena suerte!

2 comentarios:

  1. Es sumamente interesante ver como ha evolucionado la manipulación de objetos desde el lado del cliente, estoy muy de acuerdo en usar las tecnologías nativas pero no está demás aprovechar los poderosos framewortks que hay en el medio para manipular en DOM; estos FW brindan unas capacidades excepcionales para dar características visuales al usuario y además son muy fáciles de implementar; En mi caso he trabajado con Angular.js de Google y me parece increíble que hasta es capaz de simular un MVC (que lo veo más como un MV) y se pueden lograr hacer aplicaciones con muy buenas características y muy livianitas. O en cuanto a lo visual las capacidades que brinda bootstrap, es una excelente plantilla y me parece increíble el aprovechamiento de espacio que posee. Para concluir digo que todo es cuestión de gustos y me parece perfecto que HTML5 le esté apostando a incluir funciones de tan alto nivel y tan sencillas. Felicitaciones Tavo, me gustó mucho tu artículo.

    ResponderEliminar
    Respuestas
    1. Hola viejo Marvin, de acuerdo contigo, hoy en día existen diversos Frameworks para trabajo del lado del cliente mediante JavaScript, y cada uno se especializa en diferentes frentes, estos FW son sumamente poderosos y nos permiten lograr excelentes experiencias de usuario, y los estándares de la web cada vez se dan mayor cuenta de eso, es por esto que surgen estas Apis nativas en respuesta de eso, sin embargo no se trata de que la una excluya la otra, si no de tener más recursos y herramientas en conjunto como desarrolladores que nos permitan tener soluciones optimas según sea nuestro escenario. Muchas gracias por leerme y por tu excelente aporte!

      saludos!

      Eliminar