Categoría: JavaScript

  • Upload A File With HTML5 / Subir un archivo con HTML5

    Upload A File With HTML5 (XMLHttpRequest)

    Upload A File With HTML5 / Subir un archivo con HTML5

    The XMLHttpRequest object

    The XMLHttpRequest object has been updated several times since was defined as the WHATWG’s HTML effort using Microsoft technology; then we had the original XMLHttpRequest Level 1 specification as part of W3C, we also had the XMLHttpRequest Level 2 updated specification, and now we have the last version of this object known as XMLHttpRequest Living Specification. We can summarize its advantages in the following points:

    • Allows upload and download files as stream bytes, large binaries (BLOBs) or data forms
    • It has event handlers for progress, errors, abortion, start, and end of operations
    • Cross-domain capabilities (CORS)
    • New type for JSON responses
    • Is a fundamental part of the HTML5 File API specification

    It’s important to emphasize that before HTML5 and the latest versions of XMLHttpRequest object it was required to resort to server-side technology in order to able to perform an uploading file operation, that is, it wasn’t possible to upload a file natively from the client side. Technologies as AJAX and Flash did their own effort but with serious limitations, so XMLHttpRequest comes to cover this old problem in a big way. There are other additional features that come with XMLHttpRequest, if you want to know more you can resort to the official specification.

    Starting

    The first thing we’ll do is to define the user interface for this small implementation starting with the HTML tags, the code is very simple and only includes some form elements, and some div tags that are only used to give a better presentation using CSS3. I won’t analyze in this post anything related to the used cascade style sheets since is not something really necessary for the operation of this example.

    <!DOCTYPE html>
    <html>
        <head>
            <title>Upload File</title>
            <meta charset="iso-8859-1" />
        </head>
        <body>
        <div id="wrap">
           <div class="field">
               <ul class="options">
                  <li><input type="file" id="myfile" name="myfile" class="rm-input" onchange="selectedFile();"/></li>
                  <li><div id="fileSize"></div></li>
                  <li><div id="fileType"></div></li>
                  <li><input type="button" value="Subir Archivo" onClick="uploadFile()" class="rm-button" /></li>
               </ul>
           </div>
           <progress id="progressBar" value="0" max="100" class="rm-progress"></progress>
           <div id="percentageCalc"></div>
        </div>
        </body>
    </html>
    The previous code explains itself, but let’s summarize what is in there:
    • A file-type input which will be used to select the file to be uploaded
    • A div which will be used to print the size of the selected file
    • A div which will be used to print the MIME type of the selected file
    • A button which will fire the uploading process for the selected file
    • A progress bar to indicate the uploading process progress of the selected file
    • Finally, a div where the progress will be shown in a percentage format

    The selectedFile() function

    Each time you select a file using the file element, you also trigger the onchange event which calls the selectedFile() function. In this function very interesting things happen, to start, a reference to a file array instantiated by the HTML5 object FileList is done, the objects that we get as members of FileList are File objects. In this case, we’ll get the size and type properties from the gotten File object.
    Using the information provided by the size property, the size of the selected file is calculated and shown in megabytes or kilobytes within the function. With the type property, the MIME type of the selected files is gotten and showed in the corresponding div.
    function selectedFile() {
    var archivoSeleccionado = document.getElementById("myfile");
    var file = archivoSeleccionado.files[0];
       if (file) {
           var fileSize = 0;
           if (file.size > 1048576)
              fileSize = (Math.round(file.size * 100 / 1048576) / 100).toString() + ' MB';
           else
              fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + ' Kb';
    
           var divfileSize = document.getElementById('fileSize');
           var divfileType = document.getElementById('fileType');
           divfileSize.innerHTML = 'Tamaño: ' + fileSize;
           divfileType.innerHTML = 'Tipo: ' + file.type;
    
        }
    }

    The uploadFile() function

    Esta es la función que hace un mayor uso de las nuevas posibilidades de XMLHttpRequest , y es la que se encargará de disparar el proceso principal del lado cliente.

    function uploadFile(){
     //var url = "/ReadMoveWebServices/WSUploadFile.asmx/UploadFile";
     var url = "/ReadMoveWebSite/UploadMinimal.aspx";
     var archivoSeleccionado = document.getElementById("myfile");
     var file = archivoSeleccionado.files[0];
     var fd = new FormData();
     fd.append("archivo", file);
     var xmlHTTP = new XMLHttpRequest();
     //xmlHTTP.upload.addEventListener("loadstart", loadStartFunction, false);
     xmlHTTP.upload.addEventListener("progress", progressFunction, false);
     xmlHTTP.addEventListener("load", transferCompleteFunction, false);
     xmlHTTP.addEventListener("error", uploadFailed, false);
     xmlHTTP.addEventListener("abort", uploadCanceled, false);
     xmlHTTP.open("POST", url, true);
     //xmlHTTP.setRequestHeader('book_id','10');
     xmlHTTP.send(fd);
    }
    At the beginning, we have the variable url that we’ll use to indicate where is the page o web service which is going to receive the request from this page to do the proper process on server side. Immediately like in the selectedFile() function, a reference to the gotten File object member is also done.
    In the fourth line, there is something new and very useful, that is the FormData object, this object allows to instantiate a web form via JavaScript, that is, is like you put an HTML form using tags, or you can refer to an already existing one assigning it to a FormData object. No doubt this is really helpful since means now you can create a web form y alter the sending values dynamically. To append values to, either instantiated or referenced web form with FormData, use the append(file, object) method, this way in the fifth line our File object is added with the file name.
    This is the code of the function that covers what was just stated:
    //var url = "/ReadMoveWebServices/WSUploadFile.asmx/UploadFile";
    var url = "/ReadMoveWebSite/UploadMinimal.aspx";
    var archivoSeleccionado = document.getElementById("myfile");
    var file = archivoSeleccionado.files[0];
    var fd = new FormData();
    fd.append("archivo", file);

    Event handlers

    Continuing with the rest of the function, we can observe that the XMLHttpRequest object is finally instantiated and is assigned to the xmlHTTP variable, and then we proceed to the next novelty, I mean the possibility of creating new events which are part of XMLHttpRequest thanks to the upload object. The added events for this particular case are:
    • loadstart. Is triggered when the uploading file process initiates.
    • progress. Is triggered each time there is an advance in the file uploading process.
    • load. Is triggered when the transfer is complete successfully.
    • error. Is triggered when the transfer fails
    • abort. Is triggered when the user/developer interrupts the process.
    These aren’t the only available events, check the official specification for more information.
    The event handlers are declared in the following code:
    var xmlHTTP= new XMLHttpRequest();
    //xmlHTTP.upload.addEventListener("loadstart", loadStartFunction, false);
    xmlHTTP.upload.addEventListener("progress", progressFunction, false);
    xmlHTTP.addEventListener("load", transferCompleteFunction, false);
    xmlHTTP.addEventListener("error", uploadFailed, false);
    xmlHTTP.addEventListener("abort", uploadCanceled, false);

    The triggered events functions are the following:

    function progressFunction(evt){
        var progressBar = document.getElementById("progressBar");
        var percentageDiv = document.getElementById("percentageCalc");
        if (evt.lengthComputable) {
            progressBar.max = evt.total;
            progressBar.value = evt.loaded;
            percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
        }
    }
     
    function loadStartFunction(evt){
        alert('Comenzando a subir el archivo');
    }
     
    function transferCompleteFunction(evt){
        alert('Transferencia completa');
        var progressBar = document.getElementById("progressBar");
        var percentageDiv = document.getElementById("percentageCalc");
        progressBar.value = 100;
        percentageDiv.innerHTML = "100%";
    }
     
    function uploadFailed(evt) {
        alert("Hubo un error al subir el archivo.");
    }
     
    function uploadCanceled(evt) {
        alert("La operación se canceló o la conexión fue interrunpida.");
    }

    ProgressFunction() updates the progress bar and percentage which indicate in a graphical and numerical way the process progress, the rest of the functions only display the proper message for each case.

    Commented code

    If you have observed the code you probably noticed some commented lines, this is because this is just the base code to create something a little bit more complex, but I decided to leave those lines because maybe can be useful for someone:

    //var url = "/ReadMoveWebServices/WSUploadFile.asmx/UploadFile";

    The previous line of code is a call to a .Net HTTP service instead of a page. Here is where you should call your own server-side implementation.

    //xmlHTTP.upload.addEventListener("loadstart", loadStartFunction, false);

    This line calls a function that shows a message when the process starts. I commented this line after I executed the code several times because was annoying.

    The completo code

    This is how the complete implementation of the code looks:

    <!DOCTYPE html>
    <html>
        <head>
            <title>Upload File</title>
            <meta charset="iso-8859-1" />
                                        <link rel="stylesheet" type="text/css" href="estilosUploadFile.css" />
            <script type="text/javascript">
     
                  function selectedFile() {
                    var archivoSeleccionado = document.getElementById("myfile");
                    var file = archivoSeleccionado.files[0];
                    if (file) {
                        var fileSize = 0;
                        if (file.size > 1048576)
                            fileSize = (Math.round(file.size * 100 / 1048576) / 100).toString() + ' MB';
                        else
                            fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + ' Kb';
     
                        var divfileSize = document.getElementById('fileSize');
                        var divfileType = document.getElementById('fileType');
                        divfileSize.innerHTML = 'Tamaño: ' + fileSize;
                        divfileType.innerHTML = 'Tipo: ' + file.type;
     
                    }
                  }     
     
                function uploadFile(){
                    //var url = "http://localhost/ReadMoveWebServices/WSUploadFile.asmx?op=UploadFile";
                    var url = "/ReadMoveWebServices/WSUploadFile.asmx/UploadFile";
                    var archivoSeleccionado = document.getElementById("myfile");
                    var file = archivoSeleccionado.files[0];
                    var fd = new FormData();
                    fd.append("archivo", file);
                    var xmlHTTP= new XMLHttpRequest();
                    //xmlHTTP.upload.addEventListener("loadstart", loadStartFunction, false);
                    xmlHTTP.upload.addEventListener("progress", progressFunction, false);
                    xmlHTTP.addEventListener("load", transferCompleteFunction, false);
                    xmlHTTP.addEventListener("error", uploadFailed, false);
                    xmlHTTP.addEventListener("abort", uploadCanceled, false);
                    xmlHTTP.open("POST", url, true);
                    //xmlHTTP.setRequestHeader('book_id','10');
                    xmlHTTP.send(fd);
                }       
     
                function progressFunction(evt){
                    var progressBar = document.getElementById("progressBar");
                    var percentageDiv = document.getElementById("percentageCalc");
                    if (evt.lengthComputable) {
                        progressBar.max = evt.total;
                        progressBar.value = evt.loaded;
                        percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
                    }
                }
     
                function loadStartFunction(evt){
                    alert('Comenzando a subir el archivo');
                }
                function transferCompleteFunction(evt){
                    alert('Transferencia completa');
                    var progressBar = document.getElementById("progressBar");
                    var percentageDiv = document.getElementById("percentageCalc");
                    progressBar.value = 100;
                    percentageDiv.innerHTML = "100%";
                }   
     
                function uploadFailed(evt) {
                    alert("Hubo un error al subir el archivo.");
                }
     
                function uploadCanceled(evt) {
                    alert("La operación se canceló o la conexión fue interrunpida.");
                }
     
            </script>
        </head>
        <body>
            <div id="wrap">
                <div class="field">
                    <ul class="options">
                        <li>
                            <input type="file" id="myfile" name="myfile" class="rm-input" onchange="selectedFile();"/>
                        </li>
                        <li>
                            <div id="fileSize"></div></li>
                        <li>
                            <div id="fileType"></div></li>
                        <li>
                            <input type="button" value="Subir Archivo" onClick="uploadFile()" class="rm-button" /></li>
                    </ul>
                </div>
                <progress id="progressBar" value="0" max="100" class="rm-progress"></progress>
                <div id="percentageCalc"></div>
            </div>
        </body>
    </html>

    I’m not describing the CSS3 code because is irrelevant in terms of functionality, but I share an image that shows how it looks the implementation in the browser and the link to the CSS3 estilosUploadFile.zip.

    I’m also sharing the original HTTP service that I used to test this example -the server-side code, backend file or any name that you prefer 😃- but this won’t be very useful for you unless you use the exact same stack that I was using at the moment- in other words, if you are the kind of person who just wants to copy and paste….hehehe well….maybe you’re not ready for this yet. Here is the file WSUploadFile.zip

    Sorry about my English I’m not a natural speaker (don’t be grumpy, help me to improve).

    This is all for now folks, I hope this can be useful for you.

    Here some books that can help you in your HTML5 journey:

    4 Comments
  • Reseña Adobe Edge Animate 1.5

    Adobe_Edge_Animate

    Desde hace un tiempo todas aquellas personas que coqueteaban con el desarrollo de contenido multimedia pero que no tenían un perfil técnico (o como diría un antiguo colaborador: “programan poquito”) en los últimos años se han visto afectados y frustrados debido a que algunas de las herramientas que ya habían adoptado para estas labores se han visto relegadas para ciertos fines. Por ejemplo, los diseñadores gráficos que hacían elementos web como banners y headers con pequeñas animaciones, se han topado con que los clientes quieren cada vez menos al contenido creado con Flash y si hoy usted desea hacer contenido rico, animado y dinámico con los nuevos estándares sin duda requerirá de conocimientos sólidos de HTML5, Javascript y CSS3. La buena noticia es que están saliendo herramientas, que aunque quizá no cambian esta situación, sí pueden ser alternativas que hagan el terreno un poco más plano.

    Adobe en sus esfuerzos por mantenerse como uno de los líderes en el mercado de herramientas destinadas a la elaboración de recursos gráficos e interactivos, lanzó hace casi 2 años una herramienta llamada Adobe Edge que pretendía ser algo así como la herramienta de autoría sustituta para Flash, lo cual no logró además de ser ampliamente criticada (yo fui uno de esos críticos mala leche), sin embargo Adobe no ha desistido y ha seguido desarrollando su herramienta, pero ahora con el nombre de Adobe Edge Animate, y no solo eso, si no que ahora este programa es parte de una suit de interesantes aplicaciones que juntas forman la “familia” Adobe Edge. Debo mencionar que mi experiencia con este software apenas se ha reiniciado, ya que lo probé cuando salió hace dos años y no me gustó, pero al ver que Adobe seguía trabajando en él, decidí darle otra oportunidad y probarlo nuevamente.

    ¿Pero qué es Adobe Edge Animate?, es una herramienta de desarrollo web basada en HTML5, Javascript-jQuery y CSS3 y por lo tanto hace al contenido que genera “compatible” con cualquier software que pueda interpretar HTML5 (en teoría), su UI es bastante similar a cualquiera familiarizado con las herramientas multimedia basadas en línea de tiempo,  Adobe Edge Animate tiene un “stage” o área de trabajo basada en el motor Webkit que permite colocar y crear gráficos (jpeg, png, gif, svg), colocar texto, previsualizar animaciones, tiene panel de propiedades y desde luego la línea de tiempo.

    Adobe_Edge_Animate02

    La línea de tiempo utiliza “keyframes”, que así somo en Flash, ayudan a generar el “tween” entre ellos automáticamente. También se puede utilizar la herramienta Pin para animar, cada Pin permite modificar las propiedades de un elemento en algún punto de la línea de tiempo sin tener que hacer el “keyframe” de manera manual, de esta manera, usted puede crear una animación desde donde está el “playhead” hasta donde esta el Pin con todo y keyframe en un solo paso. Otra características interesante es que se pueden copiar y pegar animación de un elemento a otro, es decir, si usted tiene un circulo que se mueve de derecha a izquierda, y tiene un triángulo estático pero desea que se mueva de la misma forma que el círculo, usted únicamente copia la animación del círculo (no el elemento) y la pega en el triángulo sin tener que crear o hacer algo más.

    También puede hacer un grupo de elementos y reutilizar este en otra animación, en otras palabras puede crear símbolos (para los acostumbrados a Flash), desde luego estos símbolos pueden tener animación interna. Aunque debo decir que hay algunos problemas de reposicionamiento cuando se cambia el tamaño de la página donde se está desplegando la animación y también cuando veo la animación en Safari, no he logrado encontrar una solución efectiva…aunque como menciono apenas estoy reutilizando la herramienta otra vez…o sea, soy novato en Adobe Edge.

    Triggers!, así es, Adobe Edge utiliza mucho el mecanismo de los “triggers” para indicar que hacer cuando se llega a un determinado punto de la línea de tiempo (stop(), play(), etc.) o bien se pueden aplicar a un elemento en el área de trabajo directamente para dar respuesta a ciertos eventos, como el click del ratón o el “touch” en una tableta, todo ello por medio de una ventana separada (pop-up) de código. Si hay algún veterano del AS2 todo esto le va a recordar a la manera en la que se insertaba código en las versiones 3, 4 y 5 de Flash hace unos 14 años :p .

    He de reconocer que Adobe mejoró bastante su Adobe Edge desde la primera vez que lo utilicé, el flujo de trabajo utilizando la herramienta Pin, las herramientas de “easing” para los elementos, el copiado y pegado de animaciones y algunos otros detalles, hacen de esta aplicación algo interesante para la creación de animaciones HTML5. La parte más decepcionante para mi es que al momento no soporta audio.

    Estas son mis primeras impresiones del programa, y todas ellas las saqué gracias a que elaboré una pequeñísima y muy simple presentación para ilustrar una charla que tuve en la Facultad de Ingeniería Mecánica y Eléctrica de la Universidad de Colima, en ella se puede apreciar como diferentes navegadores responden con diferente rendimiento, lo mas notable son las diferencia en velocidad de despliegue, calidad en el rendereo de imágenes png (que son las que utilicé) y algunos problemas de posicionamiento en Safari, el mejor resultado lo obtuve en Chrome, si alguien desea probar de lo que hablo y descargar este pequeño recurso para estudiarlo, modificarlo y/o destrozarlo adelante (coloco los archivos fuentes (requieren Adobe Edge Animate) y los archivos publicados, en 2 diferentes zips):

    Fuentes

    Publicados

    *Haga clic en el nombre:
    present01

    *Haga click en cada ícono central, de izquierda a derecha:
    present02

    Update. Hace un mes aproximadamente salió Adobe Edge Animate CC que sería la versión 2.0 del programa.

    2 Comments
  • TypeDate

    Google Chrome y el INPUT[TYPE=DATE]

    Hace unos meses, cuando se lanzó la versión 20 de Google Chrome se comenzó a soportar la etiqueta Input con el type=”date” (característica de HTML5), esto debió haber sido por ahí del mes de Abril si la memoria no me falla. Sorpresivamente parece que aun varios desarrolladores no se han dado cuenta, pero otros no tardaron en mostrar cierto entusiasmo, entre ellos yo. Y creo que no es para menos, ya que aquellos que hemos batallado validando fechas en diversas plataformas, estarán de acuerdo que hacer esto puede llegar a ser un verdadero “pain in the ass”, y si por alguna razón, así como su servidor, han caído en la situación de tener que desarrollar aplicaciones o reportes destinados a finanzas sabrán el estrés que puede causar manejar fechas correctamente especialmente en estos rubros.

    Casi de inmediato comencé a probar como funcionaba, y aunque a simple vista el uso de este “nuevo control” puede parecer simple, hay algunos detalles que no son tan obvios como se pudiera pensar en un principio. Efectivamente instanciar el calendario en una página no requiere más que colocar el valor date al atributo type en una etiqueta input, así el usuario podrá ver una pequeña flecha similar a la de un select y al hacer clic se desplegará el calendario nativo de HTML5 para Chrome. Hasta aquí todo bien, pero veamos cuales son los detalles menos obvios.

    – El formato que devuelve el input

    El formato que devuelve este control es aaaa-mm-dd (o yyyy-mm-dd si lo prefiere en inglés) NO IMPORTA el formato en que se despliegue, si utiliza algo como input.valueSIEMPRE obtendrá el resultado en ese formato.

    –  El formato que acepta el input

    Si le asigna un valor al input por código de la forma input.value, el valor SOLO aceptará el formato aaaa-mm-dd, de nuevo, NO IMPORTA el formato visual en el que se despliegue la fecha.

    – ¿Cómo se envía el dato?

    Cuando utiliza un método GET o POST para enviar información, el dato también se enviará en el formato aaaa-mm-dd.

    – El formato local del sistema operativo afecta visualmente

    Si leyó los puntos anteriores notará que mencioné “el formato en que se despliega”, así es, el formato visual se ve afectado, pero únicamente por el formato que esté utilizando el sistema operativo del cliente que despliega la página donde se encuentra el input:

    – ¿Cómo se puede cambiar la apariencia del calendario emergente?

    Tristemente NO es posible, por el momento no podemos modificar la apariencia del calendario, supongo que para permitir esto Google prefiere que antes se estandarice la creación del calendario per se, habrá que esperar para ver si esto sucede en el futuro (aunque no hay garantía de que ello ocurra tampoco), por el momento habrá que conformarse.

    Puede dar un vistazo aquí y jugar un poco con el input[type=”date”].

    5 Comments
  • Arrastrar y Soltar

    Arrastrar y Soltar HTML5

    Arrastrar y Soltar

    Arrastrar y Soltar en HTML5

    Sin duda la posibilidad que introdujo HTML5 para Arrastrar y Soltar de manera nativa representó un avance, esto sin duda fue una novedad ya que en la era pre-HTML5, la única manera de lograr esto era con la utilización de complejas operaciones con JavaScript, por lo que la mayoría de los desarrolladores terminábamos utilizando alguna librería como JQuery, MooTools u otras para contar con la funcionalidad de Arrastrar y Soltar (Drag and Drop), o si la situación requería de mucha interactividad y gráficos la utilización de Flash era casi imperiosa. La clase nativa para Arrastrar y Soltar de HTML5 lleva un tiempo existiendo pero tenía varios problemas que se han ido solucionando poco a poco. El principal problema quizá era que los ejemplos que se podía encontrar por ahí, continuamente solo funcionaban en un navegador y no en los demás, pero los fabricantes han ido homologando cada vez más la clase aunque no todos todavía. La clase aún no es totalmente perfecta y tiene aún varios detractores y críticos muy enfáticos, sin embargo, posee varias ventajas sobre otras opciones. En esta entrada abordaré lo que necesita saber para comenzar a utilizar la clases Arrastrar y Soltar de HTML5 explicando sus puntos más básicos e importantes. Puede ver el ejemplo que a continuación explicaré en este enlace, comencemos…

    Ventajas sobre otras implementaciones Arrastrar y Soltar

    Como mencioné, he podido encontrar que en varios blogs aseguran que el Arrastrar y Soltar de HTML5 no debería ser utilizado, a lo cual me gustaría contra argumentar, sobre todo porque la clase me ha sido de gran ayuda últimamente:

    • Interacción con otras aplicaciones o aplicacion de derivadas. La implementación del Arrastrar y Soltar de HTML5 permite la interacción entre iframes e incluso entre ventanas de navegadores. Si me permiten ser un poco entusiasta en este punto, invito a quien sea a que intente implementar un Arrastrar y Soltar entre iframes y/o ventanas utilizando librerías JavaScript…¡el horror!….
    • El framework nativo es independiente de terceros. Tener una clase nativa siempre tiene la ventaja de independencia en cuanto a las situaciones que pueden rodear y afectar al desarrollo de un tercero, lo que evidentemente no sucede con las alternativas que presentan JQuery, MooTools, Dojo, etc., ahí la dependencia es total.
    • Interacción con aplicaciones que no son web. Un ejemplo de esto es que ahora es posible arrastrar un archivo del escritorio a una aplicación en el navegador.

    Las bases, paso a paso

    Para facilitar un poco las cosas he organizado esta entrada en pasos, cada paso describe un concepto o varios que iré ejemplificando.

    1. Especificando los elementos arrastrables (draggable object)

    Lo primero que necesita hacer es definir que nodo o nodos del documento HTML5 serán susceptibles de ser arrastrados, en HTML5 casi cualquier elemento visible puede ser arrastrado, como son imágenes, divs, links, etc., para lograr esto se utiliza el atributo draggable=”true”. Por ahora no aplica el manejo de valores falso o verdadero a  la manera clásica de XHTML en los navegadores que he probado, es decir, al atributo no funciona si lo escribimos como draggable=”draggable” incluso dentro de un archivo xhtml. También hay elementos que son arrastrables por default para algunos navegadores, como lo son imágenes y selecciones de texto. En el sigiente ejemplo se muestran algunos cuadros que serán los elementos arrastrables para este ejemplo:

    <div id="squares">
        <div class="square" draggable="true">
            <h1>1</h1>
        </div>
        <div class="square" draggable="true">
            <h1>2</h1>
        </div>
        <div class="square" draggable="true">
            <h1>3</h1>
        </div>
    </div>

    Acompañando este código colocamos los siguientes estilos CSS:

    .square {
    height: 100px;
    width: 100px;
    border: 1px solid #000;
    float: left;
    background-color: #eee;
    margin: 5px;
    -webkit-box-shadow: inset -1px -1px 3px #000;
    -ms-box-shadow: inset -1px -1px 3px #000;
    box-shadow: inset -1px -1px 3px #000;
    text-align: center;
    cursor: move;
    }
    
    h1 {
    font-size: 75px;
    }
    
    .target {
    height: auto;
    min-height: 150px;
    width: 320px;
    float: left;
    border: 1px solid #000;
    margin: 5px;
    background-color: #ccc;
    -webkit-box-shadow: inset -1px -1px 3px #000;
    -ms-box-shadow: inset -1px -1px 3px #000;
    box-shadow: inset -1px -1px 3px #000;
    text-align: center;
    cursor: move;
    }

    En navegadores webkit (Chrome, Safari) y Firefox el código anterior nos presenta una serie de cuadrados que originarán una especie de “fantasma” si intenta arrastrarlos, ahora hay que agregar los eventos apropiados. Resultado:

    2. Asignando eventos a los elementos arrastrables (Drag Objects)

    Ahora que tenemos los objetos que deseamos se puedan arrastrar, debemos asignarles algunos eventos utilizando JavaScript, estos objetos pueden disparar lo siguientes tres eventos:

    • dragstart. Se dispara cuando el usuario comienza a arrastrar el objeto.
    • drag. Se dispara cada vez que el puntero del mouse se mueve mientras que un objeto está siendo arrastrado.
    • dragend. Se dispara cuando el usuario suelta el botón mientras un objetos está siendo arrastrado. Estos eventos se asignan como lo hace normalmente JavaScript o la librería de su preferencia. Vamos a agregar unos cuantos elementos al código HTML:
    <div id="squares">
        <div class="square" draggable="true">
            <h1>1</h1>
        </div>
        <div class="square" draggable="true">
            <h1>2</h1>
        </div>
        <div class="square" draggable="true">
           <h1>3</h1>
        </div>
    </div>
    <p id="event"></p>
    <p id="status_drag"></p>
    <p id="status_over"></p>
    <p id="status_drop"></p>

    Agreguemos el siguiente código JavaScript para asignar los eventos descritos a nuestros cuadros:

    /*
    * En el evento dragstart se coloca un mensaje que se verá muy brevemente
    * o quizá no se note, cuando el usuario inicia el arrastre
    */
    function dragStartEvent(e) {
        eventStatus.innerHTML = "evento  dragStart"
    }
    
    /*
    * El evento drag reporta al usario cuando inicia y que un arrastre
    * está actualmente en progreso
    */
    function dragEvent(e) {
        eventStatus.innerHTML = "evento drag."
        dragStatus.innerHTML = "Arrastrando en este momento.";
    }
    
    /*
    * El evento dragover despliega un mensaje cuando es llamado y otro que
    * que indica que el arrastre ha terminado
    */
    function dragEndEvent(e) {
       eventStatus.innerHTML = "evento dragend."
       dragStatus.innerHTML = "Arrastre terminado."
    }
    
    //variables para elementos informativos
    var eventStatus = document.getElementById('event');
    var dragStatus = document.getElementById('status_drag');
    //variable para alamacenar todos los divs que usan la clase square
    var squareItems = document.querySelectorAll('.square');
    
    //ciclo para asignar los eventos a cada cuadro (div square)
    [].forEach.call(squareItems , function(squareItem) {
        squareItem.addEventListener('dragstart',dragStartEvent, false);
        squareItem.addEventListener('drag',dragEvent, false);
        squareItem.addEventListener('dragend',dragEndEvent, false);
    });

    Este código deber ser llamado cuando el documento HTML está cargado, note como simplemente se asignaron los eventos y estos despliegan mensajes cuando son disparados.

    3. Asignando eventos al elemento objetivo (Drop Object)

    Hasta ahora hemos logrado arrastrar elementos por la ventana, pero tenemos que asignar algún objeto en donde los elementos arrastrables puedan ser soltados, a este elemento lo llamaremos objetivo o drop target. Al elemento objetivo o drop target le podemos asignar los siguientes eventos:

    • dragenter. Se dispara cuando un objeto arrastrable es el primero en arrastrase dentro de un objeto.
    • dragover. Se dispara cuando un objeto arrastrable es arrastrado dentro de un objeto. Hay que tener presente que si se desea que el objeto que está siendo arrastrado pueda ser soltado dentro de otro, debe cancelar el comportamiento por default de este.
    • dragleave. Se dispara cuando un objeto arrastrable es arrastrado fuera de un nodo objetivo.
    • drop. Se dispara cuando un objeto arrastrable es soltado dentro de un nodo objetivo. Si desea convertir un objeto en un elemento o nodo objetivo que permita soltar elementos arrastrables, debe de asignar los eventos dragover y drop de manera obligatoria, es fácil entender porque el evento drop debe ser usado, pero quizá no sea tan claro porque dragover también, la razón es porque el elemento que se está arrastrando puede tener otro funcionamiento que no se desea cuando se suelta, por ejemplo, si está arrastrando un enlace y no previene el comportamiento por default, cuando suelte este elemento el navegador se direccionará a la URL del enlace como si usted hubiera hecho un clic normal, lo que no es deseable mientras se arrastra y se suelta el elemento. Al código que tiene actualmente, agregue al final el elemento objetivos para soltar el elemento:
    <div id="target1" class="target">Suelte elementos aquí</div>

    Agregaremos dos variables solo para alertar cuando se disparan los nuevos eventos y tener mejor idea de que el elemento objetivo está siendo efectivamente afectado.

    var overStatus = document.getElementById('status_over');
    var dropStatus = document.getElementById('status_drop');

    Y claro el código para asignar los nuevos elementos:

    dropItem.addEventListener('dragover', dragOverEvent, false);
    dropItem.addEventListener('drop', dropEvent, false);

    Los otros ventos que no incluí no son indispensables (dragenter y dragleave) pero son útiles, por ejemplo, para ofrecer más indicadores visuales al usuario y hacer una experiecia más intuitiva, pero por ahora lo omito para mayor claridad, si desea más ejemplos incluyendo estos eventos, recuerde que en el pedir está el dar 😉 Resultado:

    4. Transferecia de datos del elemento arrastrable al elemento objetivo (Datratrasfer object).

    En este punto está casi todo listo, pero donde culmina todo lo que hemos hecho es en la transferencia de datos del elemento que estamos arrastrando. Por ahora, aunque nuestro elemento parace estar haciendo todo bien, aún no lo logra ser “soltado” dentro del elemento objetivo como esperaríamos, es aquí donde la transferencia de datos hace su magia. Lo que se necesita es la propiedad dataTransfer y sus métodos setData() y getData(). Lo primero es utilizar el método setData() dentro de uno de los eventos asignados al elemento que se arrastra, usualmente se utiliza el evento dragstart, por parte de los eventos del elemento objetivo, estos pueden recibir los datos transferidos en algunos de sus eventos asignados, es ahí de donde se utiliza getData(), entonces: setData(format, data). Establece la información que se intercambia entre el nodo que se arrastra y y el nodo objetivo. El parámetro format establece el tipo de dato que se va a intercambiar, hasta ahorita los únicos tipos de dato que existan son “text” y “url” (se usa el formato de mimetype). El parámetro data es el información persé que sera intercambiada, lo cual es una cadena de texto, comunmente se utiliza innerHTML. getData(format). Recupera la información que fue previamente asignada por setData(), el setData puede estar incluso en otra página, incluso en otro navegador. El parámetro format es el tipo de dato asociado con lo que se espera, los tipos de dato pueden ser “text” y “url” (se usa el formato de mimetype). Ahora utilicemos lo que hemos aprendido en nuestro código. Dentro del evento dragstart coloquemos la siguiente línea:

    e.dataTransfer.setData('text/html', this.innerHTML);

    Con la línea anterior ha preparado la información que se va a transferir en el arrastre, ahora toca el turno de indicarle al nodo objetivo cual es información que va a recibir cuando el usuario suelte el elemento que está arrastrando, sin más agreguemos las siguientes líneas de código al evento drop:

    var dropedelement = document.createElement('span');
    dropedelement.innerHTML = e.dataTransfer.getData('text/html');
    this.appendChild(dropedelement);

    Para terminar.

    El código JavaScript completo debería lucir aproximadamente de la siguiente manera:

    /*
    * En el evento dragstart se coloca un mensaje que se verá muy brevemente
    * o quizá no se note, cuando el usuario inicia el arrastre
    */
    function dragStartEvent(e) {
        eventStatus.innerHTML = "evento  dragStart.";
        overStatus.innerHTML = "";
        dropStatus.innerHTML = "";
        e.dataTransfer.setData('text/html', this.innerHTML);
    }
    
    /*
    * El evento drag reporta al usario cuando inicia y que un arrastre
    * está actualmente en progreso
    */
    function dragEvent(e) {
        eventStatus.innerHTML = "evento drag.";
        dragStatus.innerHTML = "Arrastrando en este momento.";
    }
    
    /*
    * El evento dragover despliega un mensaje cuando es llamado y otro que
    * que indica que el arrastre ha terminado
    */
    function dragEndEvent(e) {
        eventStatus.innerHTML = "evento dragend.";
        dragStatus.innerHTML = "Arrastre terminado.";
    }
    
    /*
    * El evento dragend despliega un mensaje cuando es llamado y otro que
    * que indica sobre que elemento objetivo se arratra actualemte, si es
    * el caso
    */
    function dragOverEvent(e) {
        if (e.preventDefault) {
            e.preventDefault(); // Necesario para permitir soltar.
        }
        eventStatus.innerHTML = "evento over.";
        overStatus.innerHTML = "Elemento arrastrable sobre " + this.id;
    }
    
    /*
    * El evento drop despliega un mensaje cuando es llamado y otro que
    * que indica en que elemento objetivo se ha soltado el elemento
    */
    function dropEvent(e) {
        eventStatus.innerHTML = "evento drop";
        dropStatus.innerHTML = "Se ha soltado un elemento dentro de " + this.id;
        var dropedelement = document.createElement('span');
        dropedelement.innerHTML = e.dataTransfer.getData('text/html');
        this.appendChild(dropedelement);
    }
    
    //variables para elementos informativos
    var eventStatus = document.getElementById('event');
    var dragStatus = document.getElementById('status_drag');
    //variables para elementos informativos
    var overStatus = document.getElementById('status_over');
    var dropStatus = document.getElementById('status_drop')
    //variable para alamacenar todos los divs que usan la clase square
    var squareItems = document.querySelectorAll('.square');
    var dropItem = document.getElementById('target1');
    
    //ciclo para asignar los eventos a cada cuador (div square)
    [].forEach.call(squareItems , function(squareItem) {
        squareItem.addEventListener('dragstart',dragStartEvent, false);
        squareItem.addEventListener('drag',dragEvent, false);
        squareItem.addEventListener('dragend',dragEndEvent, false);
    });
    
    dropItem.addEventListener('dragover', dragOverEvent, false);
    dropItem.addEventListener('drop', dropEvent, false);

    Lo que obtenemos tiene este aspecto después de arrastrar todos los elementos:

    Note que este ejemplo copia los elementos en lugar de moverlos (no elimina el elemento original) pero usted puede hacerlo si lo desea. Por supuesto se pueden hacer implementaciones un tanto más sofisticadas, pero por ahora usted ha cubierto las bases para posteriormente hacer un uso más interesante e intenso de la la clase Arrastrar y Soltar de HTML5.  Si usted tiene alguna opinión, crítica, aportación o cualquier otra cosa, deje un comentario en esta entrada, o bien envíelo a @ManuGekko o @RealInernet80 en Twitter.

    Otros enlaces de interés:

    Arrancar con HTML5 Curso de Programación

    Subir un archivo con HTML5

    Transiciones y Transformaciones en Botones (CSS3 y HTML5)

    1 Comment
  • CSS Selectors

    10 CSS Selectors que hay que tener en mente

    Desde la implementación de hojas de estilo nivel 3 (CSS3) el uso de selectors en páginas web se convirtió en algo muy común, no solo por la versatilidad que ofrecen en cuanto al diseño estético de aplicaciones o páginas, si no por la enorme ventaja que implican desde el punto de vista de codificación, ya que no solo se pueden usar dentro del código CSS, si no también con los métodos de JavaScript querySelector() y querySelectorAll() que permiten un manejo mucho más dinámico de los objetos DOM de una página. Estos métodos se suman a los métodos de selección por id, clase o descendencia, implicando con esto un considerable ahorro de código.

    Cualquier entusiasta de las hojas de estilo o de HTML5 me puede reclamar la existencia de más de 10 CSS3 selectors, lo cual es totalmente cierto, pero hoy no seré tan exigente y sólo le propondré que aprenda 10 CSS selectors de uso común, que creo que todos los desarrolladores deberiamos de tener presentes, aunque claro, si desea aprenderlos  todos ¿qué mejor? (puede consultar la lista completa de selectors en la especificación oficial aquí). Utilizaré la letra E para señalar a cualquier elemento DOM.

    1. Selector E

    Permite seleccionar cualquier elemento del tipo E. Este selector no es nuevo pero si es básico e importante.

    2. Selector E[atr1]

    Selecciona el elemento E que tenga un atributo llamado atr1

    3. Selector E[atr1=”dum”]

    Selecciona el elemento E que tenga un atributo llamado atr1 cuyo valor sea exactamente dum.

    4. Selector E[atr1^=”dum”]

    Selecciona el elemento E que tenga un atributo llamado atr1 cuyo valor sea termine con la cadena de caracteres dum.

    5. Selector E[atr1$=”dum”]

    Selecciona el elemento E que tenga un atributo llamado atr1 cuyo valor sea comience con la cadena de caracteres dum.

    6. Selector E[atr1*=”dum”]

    Selecciona el elemento E que tenga un atributo llamado atr1 cuyo valor  contenga  la cadena de caracteres dum.

    7. Selector E#elid

    Selecciona el elemento E que tenga como valor del atributo id la cadena elid.

    8. Selector E:first-child

    Selecciona el primer elemento descendiente del padre del elemento E (el primer hijo).

    9. Selector E:last-child

    Selecciona el último elemento descendiente del padre del elemento E (el último hijo).

    10. Selector E:nth-child(n)

    Selecciona un elemento descendiente del padre del elemento E que se encuentre en la posición de n.

    Si alguien considera que es importante colocar otro selector en la lista y ejemplificarlo…en el pedir está el dar 🙂 . Para ver el pequeño ejemplo que utiliza todos los selectors expuestos haga click aquí.

    Enlaces de interés:

    Transiciones y Transformaciones en Botones (CSS y HTML5)

    No Comment
  • mega menu

    Cómo construir un megamenú

    Counstruir megamenú

    Megamenú

    Continuamente en la construcción  de sistemas web se requiere de la creación de menús, una necesidad común es tener que hacer menús que contengan submenús a diversos niveles, para este tipo de menús existen diversos recursos en la web que nos muestran cómo hacerlos, incluso hice una entrada donde mostré como crear una barra emergente la cual usualmente se utiliza para colocar botones de menú, ahora quizá por casualidad he visto últimamente los llamados megamenús, los cuales utilizan una estructura o layout más elaborada como los que se muestran aquí, en lugar de solo algunos “hijos” , de manera que en esta ocasión aprenderemos como hacer un bonito menú de este tipo utilizando HTML5 y CSS3 que tien la apariencia mostrada en la portada de esta entrada.

    1. Creación de la barra principal.

    La estructura básica de la barra principal del menú es muy simple, solo consta de una lista no ordenada con el tag <ul> y dentro de cada elemento de la lista se coloca una imagen (o lo que usted prefiera).

    <ul id="menu">
       <li><a href="#"><img src="opc01.png" /></a></li>
       <li><a href="#"><img src="opc02.png" /></a></li>
       <li><a href="#"><img src="opc03.png" /></a></li>
       <li><a href="#"><img src="opc04.png" /></a></li>
    </ul>

    Estilos al contenedor.

    El elemento  <ul id=”menú”> funciona como contenedor, al cual procederemos a darle estilos CSS3. En la siguiente definición se indica la eliminación del bullet que aparece comúnmente en las listas HTML, se coloca una distancia de 10 pixeles en los márgenes izquierdo y derecho, se establece el alto y ancho de la barra, la distancia interna entre el extremo de la barra y los elemento que se coloque dentro de ella, se establece un efecto de gradiente y finalmente se indica el radio para que nuestra barra tenga esquinas redondeadas:

    #menu {
       list-style:none;
       margin: 0px 10px;
       height: 57px;
       width: 900px;
       padding: 3px 5px 0px 5px;
       /*Gradientes*/
       background: -webkit-linear-gradient(top, #7f7e7e, #3f3f3f);
       background: -moz-linear-gradient(top, #7f7e7e, #3f3f3f);
       /*Esquinas redondeadas*/
       border-radius: 10px;
    }

    Estilos a los elemento de la lista.

    La definición del siguiente estilo hará que cada elemento del menú se despliegue uno  a la izquierda de otro y en bloque (como lo hace un encabezado o un párrafo) , la posición será relativa al elemento padre (ul en esta caso), las imágenes que se colocarán tendrá una distancia de 2 pixeles a todos lados excepto arriba que será de 6 pixeles, la distancia entre elementos será de 10 pixeles, se establece el ancho, tipo y color del borde de cada elemento, y por último un fondo con gradiente:

    #menu li {
       float: left;
       display: block;
       position: relative;
       padding: 6px 2px 2px 2px;
       margin-right: 10px;
       border:  1px solid #777777;
       border-radius: 5px 5px 5px 5px;
       background: -webkit-linear-gradient(top, #7f7e7e, #3f3f3f);
       background: -moz-linear-gradient(top, #7f7e7e, #3f3f3f);
    }

    Enseguida agregamos un estilo para exactamente el mismo elementos que afectamos con el estilo anterior, ¿por qué?  podría preguntarse,  la razón es que haremos que el siguiente estilo luzca diferente cuando el usuario coloca el puntero del ratón sobre el elemento del menú actual. El estilo, con la ayuda de pseudoclase hover, cambiará el color del  borde y los colores de gradientes de fondo:

    #menu li:hover  {
       border: 1px solid #bfbfbf;
       /* Color de fondo y gradientes */
       background: -moz-linear-gradient(top, #F4F4F4, #EEEEEE);
       background: -webkit-linear-gradient(top, #F4F4F4, #EEEEEE);
    }

    Para terminar el primer paso agregaremos un sencillo estilo que afectará  a los enlaces que se coloquen dentro de los elementos de menú:

    #menu li a {
       font-size: 14px;
       color: #EEEEEE;
       display: block;
       outline: 0;
       text-decoration: none;
       text-shadow: 1px 1px 1px #000;
    }

    En mi caso estoy utilizando ciertas imágenes  como elementos del menú pero usted puede utilizar las propias o sustituirlas por texto,  la siguiente imagen da una idea de lo que aproximadamente obtendrá:

    2. Haciendo los elementos emergentes (Drop Down).

    La estructura básica de los elementos emergentes consiste únicamente de que un tag <div> donde se coloca todo el contenido del elemento drop down:

    <ul id="menu">
       <li>
          <a href="#"><img src="opc01.png" /></a>
          <div class="emergente_1columna">
             Contenido del elemento emergente
          <div>
       </li>
       <li>
          <a href="#" ><img src="opc02.png" /></a>
          <div class="emergente_2columnas">
             Contenido del elemento emergente
          <div>
       </li>
    </ul>

    En la estructura de un menú drop down tradicional en lugar de divs anidaríamos otra lista, pero como en este caso deseamos un elemento mucho más elaborado utilizamos <div> para colocar lo que deseemos dentro.

    Estilos para contenedor del elemento emergente.

    He de mencionar  que la forma de organizar las columnas en algún momento la vi en el código de alguna página que implementaba un mega menú, pero no recuerdo cual fue esa página, así que espero que el autor no se moleste por la falta de crédito, aunque en realidad, como veremos,  es sencillo.

    El estilo comienza indicando que el posicionamiento es respecto a la ventana del navegador position: absolute, se envía al elemento a una gran distancia a la izquierda para que no se vea en el navegador inicialmente,  se colocan las indicaciones para posicionar los elementos dentro de nuestro contenedor, después se crea un gradiente como fondo y se finalmente redondean las esquinas.

       .emergente_1columna,
       .emergente_2columnas,
       .emergente_3columnas,
       .emergente_4columnas {
       /*Para desaparecer al elemento inicialmente*/
       position: absolute;
       left: -999em;
       text-align: left;
       padding: 10px 5px 0px 5px;
       border:1px solid #777777;
       margin-top: 3px;
       /*Gradiente de fondo*/
       background: -moz-linear-gradient(top, #EEEEEE, #BBBBBB);
       background: -webkit-linear-gradient(top, #EEEEEE, #BBBBBB);
       /*Esquinas redondeadas*/
       border-radius: 5px 5px 5px 5px;
    }

    Lo que resta en este paso es indicar el tamaño para cada elemento emergente (div) y reposicionar al mismo cuando el puntero del mouse está sobre el elemento del menú en la barra principal con la pseudoclase hover.

       .emergente_1columna {width: 160px;}
       .emergente_2columnas {width: 280px;}
       .emergente_3columnas {width: 480px;}
       .emergente_4columnas {width: 640px;}
    
       #menu li:hover .emergente_1columna,
       #menu li:hover .emergente_2columnas,
       #menu li:hover .emergente_3columnas,
       #menu li:hover .emergente_4columnas {
       left:-50%;
       top:auto;
    }

    Estilos para las columnas dentro del contenedor del elemento emergente.

    Como ha podido observar en los estilos anteriores, estamos utilizando clases de acuerdo al número máximo de columnas que habrá dentro del elemento emergente, en este caso usamos solo 4 pero puede usar tantas como usted desee, ahora crearemos contenido y estilos que actuarán sobre la(s) columnas que contiene cada elemento emergente:

    <li>
       <a href="#" title="Opción 1" ><img src="opc01.png" /></a>
       <div class="emergente_1columna">
          <div class="col_1">
              <ul>
                <li><a href="#">Superman</a></li>
                <li><a href="#">Batman</a></li>
                <li><a href="#">GreenLantern</a></li>
                <li><a href="#">Shazam!</a></li>
                <li><a href="#">Wonder Woman</a></li>
                <li><a href="#">Flash</a></li>
                <li><a href="#">Wolverine</a></li>
              </ul>
          </div>
       </div>
    </li>

    Los estilos:

       .col_1,
       .col_2,
       .col_3,
       .col_4 {
       display: inline;
       float: left;
       position: relative;
       margin-left: 5px;
       margin-right: 5px;
    }
    
    .col_1 {width:150px;}
    .col_2 {width:270px;}
    .col_3 {width:410px;}
    .col_4 {width:550px;}

    La manera de usar estos estilos en el código HTML es la siguiente:

    <ul id="menu">
       <li><a href="#" class="drop">5 Columns</a>
       <div class="dropdown_4columns">
       <div class="col_4">

    Esto es un contenido a 5 columnas.

    </div>
        <div class="col_1">

    Esto es un contenido a una columna.

    </div>
        <div class="col_2">

    Esto es un contenido a 2 columnas.

        </div>
       .
       .
       .
       </li>
    </ul>

    Y asi sucesivamente.

    Lo que obtendrá como resultado será algo similar a esto:

    3. Colocando el contenido

    En este tercer y último paso agregaremos contenido a los elementos emergentes y por supuesto haremos los estilos correspondientes, pero antes de continuar debemos de tener claro que aunque hablaremos del contenido creado para el ejemplo esta es la parte donde usted puede crear el propio y sus estilos con total libertad, de manera que los elementos emergentes muestran la información que usted desee  de la forma que más le convenga, el siguiente código es solo un ejemplo.

    Uno de los tags que manejo para mi contenido es <p> para crear párrafos, y les asigno el siguientes estilo con objetivos muy simples, solo se establece el alto de cada renglón del párrafo, el tamaño de la fuente, se orilla a la izquierda y se le coloca una sombra blanca.

    #menu p {
        line-height: 15px;
        font-size: 12px;
        text-align: left;
        text-shadow: 1px 1px 1px #FFFFFF;
    }

    Para el caso de este ejemplo utilizo más listas para incluir dentro del contenido, por lo que se agregan más elementos <ul> y <li>, como estas listas no tienen que ver con las listas que forman parte de la estructura del megamenú se asignan nuevos estilos para evitar usar los estilos de listas para el resto del menú por lo que se refrescan los estilos para tener otro apariencia para estos items:

    #menu li ul {
       list-style:none;
       padding:0px;
       margin:0 0 12px 0;
    }
    
    #menu li ul li {
       font-size: 12px;
       line-height: 25px;
       position: relative;
       text-shadow: 1px 1px 1px #ffffff;
       padding: 5px;
       margin:0 0 5px 0;
       float: none;
       text-align: left;
       width: auto;
    }
    
    #menu li ul li:hover {
       padding: 5px;
       margin:0 0 5px 0;
       width:auto;
       cursor: pointer;
    }

    Y finalmente incluí algunos estilos para un par de imágenes que se utilizan en el ejemeplo con cambios muy simples como orientar a la izquierda e incluir una sombra.

    .img_left {
       width: auto;
       float: left;
       margin: 5px 10px 1px 1px;
    }
    
    .imgshadow {
       background:#FFFFFF;
       padding:4px;
       border:1px solid #777777;
       margin-top:15px;
       -moz-box-shadow:0px 0px 5px #666666;
       -webkit-box-shadow:0px 0px 5px #666666;
       box-shadow:0px 0px 5px #666666;
    }

    El código final.

    El código completo luce como se muestra a continuación, tenga presente que este ejemplo solo ha sido probado en Chrome y en Firefox.

    HTML:

    <!DOCTYPE HTML>
    <html>
       <head>
          <meta charset="iso-8859-1">
          <title>Mega menú</title>
          <link rel="stylesheet" type="text/css" href="styles.css" />
       </head>
       <body>
           <ul id="menu">
               <li>
               <a href="#" title="Opción 1" ><img src="opc01.png" /></a>
                   <div class="emergente_1columna">
                      <div class="col_1">
                         <ul class="simple">
                             <li><a href="#">Superman</a></li>
                             <li><a href="#">Batman</a></li>
                             <li><a href="#">GreenLantern</a></li>
                             <li><a href="#">Shazam!</a></li>
                             <li><a href="#">Wonder Woman</a></li>
                             <li><a href="#">Flash</a></li>
                             <li><a href="#">Wolverine</a></li>
                         </ul>
                      </div>
                  </div>
               </li>
               <li>
                   <a href="#" title="Opción 2" ><img src="opc02.png" /></a>
                   <div class="emergente_2columnas"><!-- Begin 2 columnas container -->
                      <div class="col_2">
                         <h2>Algún Encabezado</h2>
                      </div>
                   <div class="col_2">

    Este es un ejemplo de layout que se puede utilizar, usted puede modificarlo como desee.

    Las posiblidades de CSS3 hace que puede personalizar el texto con resultados agradables.

           .
           .
           .
     
        </div>
    <div class="col_2">
        <h2>Otro encabezado</h2>
    </div>
    <div class="col_1">
        <img src="ChromeFirefox.jpg" class="imgshadow" alt="" /></div>
        <div class="col_2">

    Este menú ha sido probado en Chrome y Firefox.

       </div>
    </div>
    </li>
    <li>
       <a href="#" title="Opción 3" ><img src="opc03.png" /></a>
       <div class="emergente_3columnas"><!-- Begin 3 columnas container -->
       <div class="col_3">
       <h2>Listas</h2>
    </div>
    <div class="col_1">
       <ul class="greybox">
          <li><a href="#">HTML5</a></li>
          <li><a href="#">CSS3</a></li>
          <li><a href="#">JavaScript</a></li>
       </ul>
    </div>
    <div class="col_1">
       <ul class="greybox">
          <li><a href="#">SVG</a></li>
          <li><a href="#">WebGL</a></li>
          <li><a href="#">Más...</a></li>
       </ul>
    </div>
    <div class="col_1">
       <ul class="greybox">
          <li><a href="#">Chrome</a></li>
          <li><a href="#">FireFox</a></li>
          <li><a href="#">Opera</a></li>
       </ul>
    </div>
    <div class="col_3">
       <h2>Otra imagensita en este ejemplo</h2>
    </div>
    <div class="col_3">
       <img src="img1.png" class="img_left imgshadow" alt="" />Dolor hac. Turpis augue nec adipiscing turpis enim porta montes, porttitor integer nisi tincidunt nec nisi, scelerisque duis, in ultricies rhoncus cursus duis nec placerat dignissim cum adipiscing placerat penatibus, egestas massa dolor tincidunt scelerisque scelerisque quis porta phasellus. Auctor cras et. Natoque cursus ridiculus vut urna facilisis! Nunc mattis, tincidunt, platea sed ac? Etiam, turpis! Etiam parturient sed enim? Nisi, integer, aenean augue? Pellentesque, odio pulvinar massa, sit, porttitor urna lorem! Arcu sed et, et non, lectus! Tristique, ultricies cras? Tristique turpis hac. Sociis sit augue! Tristique, dapibus rhoncus aliquet, porta nunc ac, dictumst ac, vel platea tortor, non placerat sagittis, integer auctor mus lundium in enim. Turpis quis. Risus sociis, purus magna, enim, sagittis, mauris, eu in amet.<a href="#">Más...</a>
    
    </div>
       <!-- End 3 columnas container --></li>
       <li>
          <a href="#" title="Opción 4" ><img src="opc04.png" /></a>
          <div class="emergente_4columnas"><!-- Begin 4 columnas container -->
          <div class="col_4">
              <h2>Este es un header cualquiera</h2>
          </div>
          <div class="col_1">
              <h3>Lista de enlaces</h3>
              <ul>
                  <li><a href="#">Warcraft</a></li>
                  <li><a href="#">Starcraft</a></li>
                  <li><a href="#">Diablo</a></li>
                  <li><a href="#">Halo</a></li>
                  <li><a href="#">Ninja Gaiden</a></li>
              </ul>
          </div>
          <div class="col_1">
             <h3>Otra lista</h3>
             <ul>
                <li><a href="#">Android</a></li>
                <li><a href="#">iOS</a></li>
                <li><a href="#">Windows</a></li>
                <li><a href="#">WebOS</a></li>
                <li><a href="#">BlackBerry</a></li>
             </ul>
          </div>
          <div class="col_1">
              <h3>Más enlaces</h3>
              <ul>
                  <li><a href="#">C++</a></li>
                  <li><a href="#">C#</a></li>
                  <li><a href="#">Java</a></li>
                  <li><a href="#">HTML5</a></li>
                  <li><a href="#">ActionScript</a></li>
              </ul>
          </div>
          <div class="col_1">
              <h3>Otros...</h3>
              <ul>
                 <li><a href="#">Candice</a></li>
                 <li><a href="#">Adriana</a></li>
                 <li><a href="#">Joanna</a></li>
                 <li><a href="#">Marissa</a></li>
                 <li><a href="#">Otros...</a></li>
              </ul>
          </div>
       </div>
    <!-- End 4 columnas container --></li>
        </ul>
        </body>
    </html>

    CSS3:

    @charset "iso-8859-1";
    /* CSS Document */
    
    body{
        font-size:14px;
        font-family:Arial, Helvetica, sans-serif;
        text-align:left;
    }
    
    #menu {
        list-style:none;
        margin: 0px 10px;
        height: 57px;
        width:900px;
        padding: 3px 5px 0px 5px;
        /*Gradientes*/
        background: -webkit-linear-gradient(top, #7f7e7e, #3f3f3f);
        background: -moz-linear-gradient(top, #7f7e7e, #3f3f3f);
        /*Esquinas redondeadas*/
        border-radius: 10px;
    }
    
    #menu li {
       float:left;
       display:block;
       position:relative;
       padding: 6px 2px 2px 2px;
       margin-right: 10px;
       border: 1px solid #777777;
       border-radius: 5px 5px 5px 5px;
       background: -webkit-linear-gradient(top, #7f7e7e, #3f3f3f);
       background: -moz-linear-gradient(top, #7f7e7e, #3f3f3f);
    }
    
    #menu li:hover {
        border: 1px solid #bfbfbf;
        /* Color de fondo y gradientes */
        background: -moz-linear-gradient(top, #F4F4F4, #EEEEEE);
        background: -webkit-linear-gradient(top, #F4F4F4, #EEEEEE);
    }
    
    #menu li a {
        font-size: 14px;
        color: #EEEEEE;
        display: block;
        outline: 0;
        text-decoration: none;
        text-shadow: 1px 1px 1px #000;
    }
    
    /* Estilos para las columnas */
        .emergente_1columna,
        .emergente_2columnas,
        .emergente_3columnas,
        .emergente_4columnas {
        /*Para desaparecer al elemento inicialmente*/
        position: absolute;
        left: -999em;
        text-align: left;
        padding: 10px 5px 0px 5px;
        border:1px solid #777777;
        margin-top: 3px;
        /*Gradiente de fondo*/
        background: -moz-linear-gradient(top, #EEEEEE, #BBBBBB);
        background: -webkit-linear-gradient(top, #EEEEEE, #BBBBBB);
        /*Esquinas redondeadas*/
        border-radius: 5px 5px 5px 5px;
    }
    
    .emergente_1columna {width: 160px;}
    .emergente_2columnas {width: 280px;}
    .emergente_3columnas {width: 480px;}
    .emergente_4columnas {width: 640px;}
    
    #menu li:hover .emergente_1columna,
    #menu li:hover .emergente_2columnas,
    #menu li:hover .emergente_3columnas,
    #menu li:hover .emergente_4columnas {
       left:-50%;
       top:auto;
    }
    
    .col_1,
    .col_2,
    .col_3,
    .col_4 {
       display:inline;
       float: left;
       position: relative;
       margin-left: 5px;
       margin-right: 5px;
    }
    
    .col_1 {width:150px;}
    .col_2 {width:270px;}
    .col_3 {width:410px;}
    .col_4 {width:550px;}
    #menu li ul {
       list-style:none;
       padding:0px;
       margin:0 0 12px 0;
    }
    
    #menu li ul li {
       font-size: 12px;
       line-height: 25px;
       position: relative;
       text-shadow: 1px 1px 1px #ffffff;
       padding: 5px;
       margin:0 0 5px 0;
       float: none;
       text-align: left;
       width: auto;
    }
    
    #menu li ul li:hover {
       padding: 5px;
       margin:0 0 5px 0;
       width:auto;
       cursor: pointer;
    }
    
    #menu p {
       line-height: 15px;
       font-size: 12px;
       text-align: left;
       text-shadow: 1px 1px 1px #FFFFFF;
    }
    
    /*Para las imagenes en los submenus*/
    .img_left {
       width: auto;
       float: left;
       margin: 5px 10px 1px 1px;
    }
    
    .imgshadow {
       background:#FFFFFF;
       padding:4px;
       border:1px solid #777777;
       margin-top:15px;
       -moz-box-shadow:0px 0px 5px #666666;
       -webkit-box-shadow:0px 0px 5px #666666;
       box-shadow:0px 0px 5px #666666;
    }

    Código descargable aquí.

    Estos son algunos libros que le pueden ayudar:

    No Comment
  • Barra Emergente

    Crear una barra emergente con HTML5, CSS3 y JQuery

    Barra emergente con html5

    ¿De que va esta barra emergente?

    Hoy mostraré como hacer una barra emergente que aparece en la parte superior del navegador, este tipo de barras pueden ser útiles para colocar mensajes, botones de herramientas, etc. La idea surgió cuando vi la llamada “Hello Bar” de este sitio hellobar.com, de manera que me dí a la tarea de crear algo similar.

    HelloBar
    Barra de hellobar.com

    He probado el resultado del código que le presentaré únicamente en Chrome y en Firefox, por lo que podría no funcionar adecuadamente en otros navegadores, pero si usted desea hacer las adecuaciones necesarias en esos casos…¡adelante! y espero comparta sus resultados 🙂 .

    Puede ver el demo de la barra en jsfiddle.net:

    1. Creación de la estructura del documento HTML5.

    Primeramente elabore la estructura general de su página, para ello cree un nuevo archivo HTML y coloque el siguiente código en el:

    <!DOCTYPE html>
    <html>
       <head>
          <meta "charset=iso-8859-1" />
          <script src='libs/jquery-1.7.1.min.js'></script>
          <script src='libs/jquery-ui-1.8.18.custom.min.js'></script>
          <title>Barra Emergente</title>
       </head>
      <body>
        <header>
          <div id="popup">
            <a href=# class="hide"></a>
            <nav id="header_nav_menu">
    
              <a href="#" class="btn_new_page" title="New Book"></a>
              <a href="#" class="btn_page" title="New Page"></a>
    
              <div class="dropdown_area">
                <div class="dropdown-content">
                  <div class="header">
                    <h2>Mega Menu</h2>
                  </div>
                  <div class="row">
                    <div class="column">
                      <h3>Category 1</h3>
                      <a href="#">Link 1</a>
                      <a href="#">Link 2</a>
                      <a href="#">Link 3</a>
                    </div>
                    <div class="column">
                      <h3>Category 2</h3>
                      <a href="#">Link 1</a>
                      <a href="#">Link 2</a>
                      <a href="#">Link 3</a>
                    </div>
                  </div>
                </div>
              </div>
    
    
            </nav>
            <div id="hide_area">&and;</div>
          </div>
          <div id="showpop">
            <a href="#" class="showpoplink"></a>
            &or;
          </div>
        </header>
        <article>
          <p>
            <br/>Contenido en la página</p>
          <p>Más cóntenido en la página</p>
        </article>
    
      </body>
    </html>

    Analicemos un poco, si nunca ha hecho páginas HTML5 antes, entonces no sobra decir que la etiqueta <!DOCTYPE html> es la “señal” que utilizan los navegadores para saber que el código del archivo es HTML5 y no una versión previa. Por otro lado, el fragmento de código que contiene los elementos que conforman la barra emergente en si misma es:

    <div id="popup">
       <a href=# class="hide"></a>
       <nav id="header_nav_menu">
    
         <a href="#" class="btn_new_page" title="New Book"></a>
         <a href="#" class="btn_page" title="New Page"></a>
    
         <div class="dropdown_area">
           <div class="dropdown-content">
             <div class="header">
               <h2>Mega Menu</h2>
             </div>
             <div class="row">
               <div class="column">
                 <h3>Category 1</h3>
                 <a href="#">Link 1</a>
                 <a href="#">Link 2</a>
                 <a href="#">Link 3</a>
               </div>
               <div class="column">
                 <h3>Category 2</h3>
                 <a href="#">Link 1</a>
                 <a href="#">Link 2</a>
                 <a href="#">Link 3</a>
               </div>
             </div>
           </div>
         </div>
    
    
       </nav>
     <div id="hide_area">&and;</div>
    

    El código anterior básicamente crea un elemento div que contiene un enlace que servirá para ocultar la barra cuando se hace clic en el, adicionalmente se colocan otros tres enlaces, que solo sirven como ejemplo de contenido que aparece dentro de la barra emergente en este ejercicio, estos enlaces pueden ser sustituidos por el contenido que más le convenga.

    Note también este código:

    <div id="showpop" >
    <a href="#" class="showpoplink"></a>
    &or;
    </div>

    Este div aparacerá cuando la barra esté escondida y servirá para mostrarla de nuevo cuando se hace clic.

    Ahora bien, para hacer funcional a nuestro ejercicio hecharemos mano de la popular librería JQuery y su complemento para efectos visuales JQuery UI, si no esta familiarizado con con JQuery lo único que debe de saber al momento es que, fundamentalmente, JQuery es un conjunto de funciones JavaScript que conforman una amplia librería que le puede evitar una gran cantidad de trabajo, que de otra manera tendría que desarrollar usted mismo.

    Para este ejercicio descargué y coloqué ambas librerías en una carpeta llamada libs, pero puede colocarlas donde usted desee haciendo la corrección pertinente en la siguientes líneas de código.

    Para JQuery:

    <script src='libs/jquery-1.7.1.min.js'></script>

    Para JQuery UI:

    <script src='libs/jquery-ui-1.8.18.custom.min.js'></script>

    2. Agregar funcionalidad

    Para lograr que el código creado reaccione a las acciones del usuario, que para el caso son solo dos, ocultar y mostrar la barra, utilizaremos el siguiente código:

    <script type="text/javascript">
       $(document).ready(function(){
          $('#popup').show("bounce", { times:3 }, 350);
          $('#showpop').hide();
          $('.hide').click(function(){
             $('#popup').slideUp();
             $('#showpop').fadeIn('slow');
             return false;
          });
          $('a.showpoplink').click(function(){
             $('#popup').show("bounce", { times:3 }, 350);
             $('#showpop').hide();
            return false;
          });
        });
    </script>

    Lo que sucede gracias a este código es lo siguiente, cuando el documento HTML5 es reportado como “listo” por parte del navegador, inmediatamente la barra se muestra con en efecto de rebote, mientras que el enlace que sirve para mostrar la barra se oculta ya que no es necesario cuando la barra está visible:

    $('#popup').show("bounce", { times:3 }, 350);
    $('#showpop').hide();

    Al mismo tiempo se indica cual botón dentro de la barra debe servir para ocultarla haciendo clic:

    $('.hide').click(function(){
        $('#popup').slideUp();
        $('#showpop').fadeIn('slow');
        return false;
    });

    Finalmente, se hace los mismo pero para el caso del enlace que servirá para mostrar la barra cuando esta está oculta, utilizando el mismo efecto de rebote se ve en la carga inicial:

    $('a.showpoplink').click(function(){
        $('#popup').show("bounce", { times:3 }, 350);
        $('#showpop').hide();
        return false;
    });

    3. Estilizar y ordenar los elementos.

    Finalmente no queda más que darle belleza y orden a nuestros elementos HTML utilizando una hoja de estilos, veamos estos poco a poco para tener mejor idea de que hacemos.

    body {
       margin:0;
       padding:0;
    }
    
    #popup {
       top: 0;
       width: 100%;
       padding: 20px 0px 0px 0px;
       height: 50px;
       background-image: linear-gradient(bottom, rgb(238,238,238) 14%, rgb(249,249,249) 60%);
       background-image: -o-linear-gradient(bottom, rgb(238,238,238) 14%, rgb(249,249,249) 60%);
       background-image: -moz-linear-gradient(bottom, rgb(238,238,238) 14%, rgb(249,249,249) 60%);
       background-image: -webkit-linear-gradient(bottom, rgb(238,238,238) 14%, rgb(249,249,249) 60%);
       background-image: -ms-linear-gradient(bottom, rgb(238,238,238) 14%, rgb(249,249,249) 60%);
       -moz-box-shadow: 0 0 5px 5px #bfbfbf;
       -webkit-box-shadow: 0 0 5px 5px#bfbfbf;
       box-shadow: 0 0 5px 5px #bfbfbf;
       display: block;
       /*position: fixed;*/
    }

    Los estilos anteriores se encargan primeramente de eliminar cualquier espacio entre el cuerpo del documento HTML y los elementos que contiene mediante la personalización de la etiqueta body. Enseguida se indica el aspecto que tendrá el div que contiene a la propia barra con el estilo #popup, ahí se indica la posición, el ancho y alto de la misma. Utilizamos las nuevas características de CSS3 para dar un gradiente al fondo de la barra y darle un discreto sombreado; en versiones anteriores de CSS esto no hubiera sido posible y tendría que haber creado una imagen previamente, tendría que colocarla y repetirla como fondo, esto ya no es necesario gracias a CSS3.

    Ahora toca el turno de configurar el tamaño de el área sensible dentro de la barra para poder ocultarla:

    #hide_area{
       width: inherit ;
       background: #666;
       padding: 0px;
       margin: 20px 0px 0px 0px;
       color:#FFF;
       font-family:Verdana, Geneva, sans-serif;
       font-size:10px;
       font-weight:bold;
       text-align:center;
       /*border:solid;*/
    }
    
    a.hide {
       top: 0;
       width: 100%;
       margin-top: 50px;
       padding: 8px 0px 8px 0px;
       display: block;
       cursor:default;
       position: fixed;
       /*border:solid;*/
    }

    Los estilos anteriores solo se encargan de definir el tamaño, posición y colores utilizados por el enlace que funciona como área sensible para poder ocultar la barra al hacer clic.

    Ahora se hace lo mismo pero para el enlace que muestra la barra cuando se hace clic:

    #showpop{
       top: 0;
       width: 100%;
       height: 14px;
       background: #666;
       padding: 0px;
       margin: 0px 0px 0px 0px;
       -moz-box-shadow: 0 0 5px 5px #bfbfbf;
       -webkit-box-shadow: 0 0 5px 5px#bfbfbf;
       box-shadow: 0 0 5px 5px #bfbfbf;
       color:#FFF;
       font-family: Verdana, Geneva, sans-serif;
       font-size: 10px;
       font-weight: bold;
       text-align: center;
       position: fixed;
      /*border:solid;*/
    }
    
    a.showpoplink {
       top: 0;
       width: 100%;
       margin-top: 0px;
       padding: 5px 0px 5px 0px;
       display: block;
       cursor:default;
       position: fixed;
       /*border:solid;*/
    }

    Para terminar, he agregado unos botones que funcionan como contenido dentro de la barra emergente que se ha creado, para definir su aspecto utilicé los siguientes estilos, por supuesto usted tendrá que desarrollar los suyos para su propio contenido:

    #header_nav_menu a {
      padding: 0px 13px 10px 13px;
      background-repeat: no-repeat;
      cursor: pointer;
      /*border:solid;*/
    }
    
    #header_nav_menu a.btn_new_page {
      background-image: url('http://icons.iconarchive.com/icons/gakuseisean/ivista-2/24/Files-New-File-icon.png');
    }
    
    #header_nav_menu a.btn_page {
      background-image: url('http://icons.iconarchive.com/icons/dryicons/aesthetica-2/24/page-icon.png');
    }
    
    
    /* Dropdown content (hidden by default) / Contenido del dropdown escondido por default*/
    
    .dropdown-content {
      display: none;
      position: absolute;
      background-color: #f9f9f9;
      width: 50%;
      left: 0;
      box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
      z-index: 1;
    }
    
    .dropdown_area {
      padding: 0px 13px 25px 13px;
      background-repeat: no-repeat;
      cursor: pointer;
      background-image: url('http://icons.iconarchive.com/icons/double-j-design/super-mono-3d/24/button-dropdown-icon.png');
      float: left;
    }
    
    
    /* Show the dropdown menu on hover / Muestra del dropdwon al colar el mouse sobre el botón*/
    
    .dropdown_area:hover .dropdown-content {
      display: block;
      margin-top: 25px;
    }
    
    
    /* Mega Menu header, if needed */
    
    .dropdown-content .header {
      background: gray;
      padding: 10px;
      color: white;
    }
    
    h3 {
      padding: 5px;
    }
    
    
    /* Create two equal columns that floats next to each other / Crear dos columnas iguales que flotan una junto a la otra */
    
    .column {
      font-size: 14px;
      float: left;
      width: 50%;
      background-color: #ccc;
      height: 100px;
    }
    
    
    /* Style links inside the columns / Estilos para los enlaces dentro de columnas */
    
    .column a {
      float: none;
      color: black;
      padding: 16px;
      text-decoration: none;
      display: block;
      text-align: left;
    }
    
    
    /* Add a background color on hover / Añade color a los enlaces cuando se pone el mouse encima */
    
    .column a:hover {
      background-color: #ddd;
    }
    
    
    /* Clear floats after the columns / Limpia los floats despues de las columnas */
    
    .row:after {
      content: "";
      display: table;
      clear: both;
    }

    Conclusión.

    Si llegó hasta este punto es porque seguramente ha hecho un buen trabajo, siéntase libre de jugar con este pequeño ejemplo, me encantaría ver sus resultados así que no dude en compartirlos.

    Enlaces de interes:

    Subir un archivo con HTML5

    Arrastrar y Soltar HTML5

    Aquí algunos libros que le pueden ayudar:

    No Comment
  • Upload A File With HTML5 / Subir un archivo con HTML5

    Subir un archivo con HTML5

    Upload A File With HTML5 / Subir un archivo con HTML5

    El objeto XMLHttpRequest

    El objeto XMLHttpRequest ha sido actualizado varias veces desde que fue definido como parte del esfuerzo WHATWG’s HTML utilizando la tecnología de Microsoft; entonces tuvimos la especificación original XMLHttpRequest Level 1 como parte de la W3C, también tuvimos la especificación actualizada XMLHttpRequest Level 2, y ahora tenemos la últma version de este documento conocido como XMLHttpRequest Living Specification. Podemo resumir sus ventajas en los siguientes puntos:

    • Permite subir y bajar archivos como flujo de bytes (stream bytes), archivos binarios de gran tamaño (BLOBs) o formularios de datos.
    • Tiene manejadores de eventos de progreso, errores, aborto, comienzo, y fin de operaciones.
    • Peticiones inter dominio (cross-domain or CORS)
    • Nuevos tipos de respuestas para JSON
    • Es parte fundamental de la HTML5 File API specification

    Es importante recalcar que antes de HTML5 y la nueva versión del objeto XMLHttpRequest se requería recurrir a tecnología de lado servidor para poder realizar una operación que permitiera subir un archivo, es decir no era posible subir un archivo nativamente del lado cliente. Tecnologías como AJAX  y Flash hacían lo propio para tratar de hacer esto posible pero con serias limitaciones, por lo que XMLHttpRequest viene a cubrir este antiguo problema de gran manera. Existen otras características adicionales que acomapañan XMLHttpRequest  Level 2 , si desea conocer más puede recurrir a  la especificación oficial.

    La mayoría de las veces utilizo código y comentarios en inglés, espero que esto no le resulte demasiado inconveniente, si tiene alguna duda la contestaré a la brevedad.

    Comenzando

    Lo primero que haremos es definir la interfaz de usuario para esta pequeña implementación comenzando por las etiquetas HTML, el código es muy sencillo y solo contempla algunos elementos de formulario, y algunos div que solo sirven para dar una mejor presentación auxiliandose de CSS3. No analizaré en este post lo que respecta a las hojas de estilo utilizadas ya que no es algo necesario para el funcionamiento del ejemplo.

    <!DOCTYPE html>
    <html>
     <head>
     <title>Upload File</title>
     <meta charset="iso-8859-1" />
     </head>
     <body>
    <div id="wrap">
    <div class="field">
    <ul class="options">
     <li>
     <input type="file" id="myfile" name="myfile" class="rm-input" onchange="selectedFile();"/></li>
     <li>
    <div id="fileSize"></div></li>
     <li>
    <div id="fileType"></div></li>
     <li>
     <input type="button" value="Subir Archivo" onClick="uploadFile()" class="rm-button" /></li>
    </ul>
    </div>
    <progress id="progressBar" value="0" max="100" class="rm-progress"></progress>
    <div id="percentageCalc"></div>
    </div>
    </body>
    </html>

    El código anterior se explica casi por si solo, pero resumamos lo que tiene:

    • Un input de tipo file que servirá para seleccionar el archivo que se desa subir.
    • Un div que servirá para imprimir el tamaño del archivo seleccionado.
    • Un div que servirá para imprimir el tipo MIME del archivo seleccionado.
    • Un botón que disparará el proceso para subir el archivo elegido.
    • Una barra que indicará el progreso en el proceso de subida del archivo (nuevo elemento HTML5).
    • Finalmente un div donde se mostrará el progreso en formato de porcentaje.

    La función selectedFile()

    Cada vez que selecciona un archivo con el elemento file,  también dispara al evento onchange el cual llama a la función selectedFile(). En esta función suceden cosas interesantes, para empezar se hace referencia a una colección de archivos instanciada por un objeto nuevo en HTML5 llamado FileList, los objetos que obtenemos como miembros de las lista de FilesList son objetos File. En este caso obtendremos las propiedades size y type desde el objeto File recuperado.

    Aprovenchando la información que proporciona la propiedad size, dentro de la función se calcula y se muestra en megabytes o kilobytes el tamaño del archivo que se ha seleccionado. Con la propiedad type se obtiene el tipo MIME del archivo seleccionado, el cual se muestra en el div correspondiente.

    function selectedFile() {
    var archivoSeleccionado = document.getElementById("myfile");
    var file = archivoSeleccionado.files[0];
       if (file) {
           var fileSize = 0;
           if (file.size > 1048576)
              fileSize = (Math.round(file.size * 100 / 1048576) / 100).toString() + ' MB';
           else
              fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + ' Kb';
    
           var divfileSize = document.getElementById('fileSize');
           var divfileType = document.getElementById('fileType');
           divfileSize.innerHTML = 'Tamaño: ' + fileSize;
           divfileType.innerHTML = 'Tipo: ' + file.type;
    
        }
    }

    La función uploadFile()

    Esta es la función que hace un mayor uso de las nuevas posibilidades de XMLHttpRequest , y es la que se encargará de disparar el proceso principal del lado cliente.

    function uploadFile(){
     //var url = "/ReadMoveWebServices/WSUploadFile.asmx/UploadFile";
     var url = "/ReadMoveWebSite/UploadMinimal.aspx";
     var archivoSeleccionado = document.getElementById("myfile");
     var file = archivoSeleccionado.files[0];
     var fd = new FormData();
     fd.append("archivo", file);
     var xmlHTTP = new XMLHttpRequest();
     //xmlHTTP.upload.addEventListener("loadstart", loadStartFunction, false);
     xmlHTTP.upload.addEventListener("progress", progressFunction, false);
     xmlHTTP.addEventListener("load", transferCompleteFunction, false);
     xmlHTTP.addEventListener("error", uploadFailed, false);
     xmlHTTP.addEventListener("abort", uploadCanceled, false);
     xmlHTTP.open("POST", url, true);
     //xmlHTTP.setRequestHeader('book_id','10');
     xmlHTTP.send(fd);
    }

    Inicialmente tenemos una variable url que usaremos para indicar donde está la página o servicio web que recibirá la petición de esta página para hacer el proceso indicado en el servidor; enseguida tal y como se hizo en la funcion selectedFile() se hace referencia al objeto File miembro FileList obtenido.

    En la cuarta línea hay algo novedoso y muy útil, me refiero al objeto FormData,  este objeto permite instanciar vía JavaScript un formulario web, es decir, es como si usted colocara con etiquetas HTML un formulario, o bien puede hacer referencia a uno ya existente asignándolo a un objeto FormData. Sin duada esto es de gran ayuda ya que significa que ahora usted puede crear un formulario y alterar los valores que envía de manera dinámica. Para adjuntar valores a un formualrio instanciado o referenciado con FormData se utiliza el método append(archivo, objeto), de esta manera en la quinta línea se agrega nuestro objeto File con el nombre de archivo.

    Este es el fragmento de la función que abarca lo planteado:

    //var url = "/ReadMoveWebServices/WSUploadFile.asmx/UploadFile";
    var url = "/ReadMoveWebSite/UploadMinimal.aspx";
    var archivoSeleccionado = document.getElementById("myfile");
    var file = archivoSeleccionado.files[0];
    var fd = new FormData();
    fd.append("archivo", file);

    Manejadores de eventos

    Continuando con el resto de la función, podemos observar que finalmente instancía el objeto XMLHttpRequest  y se asigna a la variable xmlHTTP, enseguida procedemos a la siguiente novedad, me refiero a la posibilidad de crear los nuevos eventos que forman parte de XMLHttpRequest  Level 2 gracias al objeto upload. Los eventes que se agregan en este caso son:

    • loadstart. Evento que se dispara cuando inicia el proceso para subir el archivo.
    • progress. Evento que se dispara cada vez que hay un avance en el proceso que sube el archivo.
    • load. Evento que se dispara cuando la transferecia se completa.
    • error. Se dispara si el proceso falla con error explícito.
    • abort. Se dispara si el usuario interrumpe o la conexión de interrumpe.

    No son los único eventos disponibles, consulte la especificación oficial para mayor información.

    Los manejadores de eventos se declaran en el siguiente código:

    var xmlHTTP= new XMLHttpRequest();
    //xmlHTTP.upload.addEventListener("loadstart", loadStartFunction, false);
    xmlHTTP.upload.addEventListener("progress", progressFunction, false);
    xmlHTTP.addEventListener("load", transferCompleteFunction, false);
    xmlHTTP.addEventListener("error", uploadFailed, false);
    xmlHTTP.addEventListener("abort", uploadCanceled, false);

    Las funciones que se llaman en cada evento son las siguientes:

    function progressFunction(evt){
        var progressBar = document.getElementById("progressBar");
        var percentageDiv = document.getElementById("percentageCalc");
        if (evt.lengthComputable) {
            progressBar.max = evt.total;
            progressBar.value = evt.loaded;
            percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
        }
    }
     
    function loadStartFunction(evt){
        alert('Comenzando a subir el archivo');
    }
     
    function transferCompleteFunction(evt){
        alert('Transferencia completa');
        var progressBar = document.getElementById("progressBar");
        var percentageDiv = document.getElementById("percentageCalc");
        progressBar.value = 100;
        percentageDiv.innerHTML = "100%";
    }
     
    function uploadFailed(evt) {
        alert("Hubo un error al subir el archivo.");
    }
     
    function uploadCanceled(evt) {
        alert("La operación se canceló o la conexión fue interrunpida.");
    }

    La función progressFunction es la que actualiza tanto la barra de estado como el porcentaje que indican de manera gráfica y numérica el avance del proceso, el resto de las funciones únicamente despliegan un mensaje apropiado para el caso.

    Código comentado

    Si ha observado el código presentado habrá notado algunas líneas comentadas, eso es debido a que este es el código base para hacer algo un poco más complejo, pero decidí dejar esas líneas porque pueden ser una referencia útil para alguien:

    //var url = "/ReadMoveWebServices/WSUploadFile.asmx/UploadFile";

    La línea anterior es una llamada a un servicio HTTP .Net en lugar de a una página.

    //xmlHTTP.upload.addEventListener("loadstart", loadStartFunction, false);

    Esta línea llama a una función que muestra un mensaje cuando inicia el proceso, la cual comenté porque después de ejecuar varias veces el código me pareció molesto.

    El código completo

    Así luce la implementación completa del código, no describo el código CSS3 ya que es irrelevante en lo que respecta a la funcionalidad, pero comparto una imágen que muestra como se ve ejecutándose:

    <!DOCTYPE html>
    <html>
        <head>
            <title>Upload File</title>
            <meta charset="iso-8859-1" />
                                        <link rel="stylesheet" type="text/css" href="estilosUploadFile.css" />
            <script type="text/javascript">
     
                  function selectedFile() {
                    var archivoSeleccionado = document.getElementById("myfile");
                    var file = archivoSeleccionado.files[0];
                    if (file) {
                        var fileSize = 0;
                        if (file.size > 1048576)
                            fileSize = (Math.round(file.size * 100 / 1048576) / 100).toString() + ' MB';
                        else
                            fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + ' Kb';
     
                        var divfileSize = document.getElementById('fileSize');
                        var divfileType = document.getElementById('fileType');
                        divfileSize.innerHTML = 'Tamaño: ' + fileSize;
                        divfileType.innerHTML = 'Tipo: ' + file.type;
     
                    }
                  }     
     
                function uploadFile(){
                    //var url = "http://localhost/ReadMoveWebServices/WSUploadFile.asmx?op=UploadFile";
                    var url = "/ReadMoveWebServices/WSUploadFile.asmx/UploadFile";
                    var archivoSeleccionado = document.getElementById("myfile");
                    var file = archivoSeleccionado.files[0];
                    var fd = new FormData();
                    fd.append("archivo", file);
                    var xmlHTTP= new XMLHttpRequest();
                    //xmlHTTP.upload.addEventListener("loadstart", loadStartFunction, false);
                    xmlHTTP.upload.addEventListener("progress", progressFunction, false);
                    xmlHTTP.addEventListener("load", transferCompleteFunction, false);
                    xmlHTTP.addEventListener("error", uploadFailed, false);
                    xmlHTTP.addEventListener("abort", uploadCanceled, false);
                    xmlHTTP.open("POST", url, true);
                    //xmlHTTP.setRequestHeader('book_id','10');
                    xmlHTTP.send(fd);
                }       
     
                function progressFunction(evt){
                    var progressBar = document.getElementById("progressBar");
                    var percentageDiv = document.getElementById("percentageCalc");
                    if (evt.lengthComputable) {
                        progressBar.max = evt.total;
                        progressBar.value = evt.loaded;
                        percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
                    }
                }
     
                function loadStartFunction(evt){
                    alert('Comenzando a subir el archivo');
                }
                function transferCompleteFunction(evt){
                    alert('Transferencia completa');
                    var progressBar = document.getElementById("progressBar");
                    var percentageDiv = document.getElementById("percentageCalc");
                    progressBar.value = 100;
                    percentageDiv.innerHTML = "100%";
                }   
     
                function uploadFailed(evt) {
                    alert("Hubo un error al subir el archivo.");
                }
     
                function uploadCanceled(evt) {
                    alert("La operación se canceló o la conexión fue interrunpida.");
                }
     
            </script>
        </head>
        <body>
            <div id="wrap">
                <div class="field">
                    <ul class="options">
                        <li>
                            <input type="file" id="myfile" name="myfile" class="rm-input" onchange="selectedFile();"/>
                        </li>
                        <li>
                            <div id="fileSize"></div></li>
                        <li>
                            <div id="fileType"></div></li>
                        <li>
                            <input type="button" value="Subir Archivo" onClick="uploadFile()" class="rm-button" /></li>
                    </ul>
                </div>
                <progress id="progressBar" value="0" max="100" class="rm-progress"></progress>
                <div id="percentageCalc"></div>
            </div>
        </body>
    </html>

    No descibo el CSS3 porque es irrelevante en términos de funcionalidad, pero comparto una imagen que muestra como luce la implementación en el navegador y un enlace al CSS3 estilosUploadFile.zip.

    También comparto el HTTP service que utilicé para este ejemplo (el código de lado servidor, archivo de backend o cualquier otro nombre que ud. prefiera 😃) pero esto no será de mucha ayuda amenos que utilice exactemente el mismo stack que yo utilicé en su momento. En otras palabras, si usted es el tipo de personas que solo quiera copiar y pegar….jejeje bueno…quizá no está listo para hace esto todavía. Aquí está el tan solicitado archivo WSUploadFile.zip

    Es todo por ahora amigos, espero que esto les sea de utilidad.

    Algunos buenos libros que pueden ayudarle en su viaje por HTML5:

    39 Comments
  • Utilice getElementsByClassName

    JScode

    JavaScript y DOM han ido mejorando con el tiempo, y especialmente en la marco de HTML5, una de esas mejoras es el método getElementsByClassName(NombreClase) el cual nos permite obtener varios elementos al mismo tiempo. Desde hace años los desarrolladores contamos con getElementById con la limitante de obtener únicamente un solo elemento; más recientemente QuerySelector y QuerySelectorAll los cuales son métodos poderosos y flexibles. Sienodo así ¿porque deberiamos usar getElementsByClassName?

    Los casos donde pude preferir utilizar getElementsByClassName son aquellos donde usted tiene un árbol de elementos extenso y/o complejo, si ese es el caso y usted desea modificar elementos independientemente de su posición y sin usar selector complejos, entonces usted puede recuperar esa colección con todos elementos que utilizan la clase o clases seleccionadas. Cabe destacar que bajo ese escenario las pruebas de benchmarking tienden a favorecer a getElementsByClassName sobre QuerySelector y QuerySelectorAll.

    Esto supone una gran ventaja en términos de cantidad de código, ya que el método puede seleccionar varios elemento de una sola vez pero también discriminar implicitamente algunos sin usar selectors elaborados. El comportamiento de getElementsByClassName  es básicamente buscar en todo el documento a todos los elementos que cumplan con el criterio de búsqueda  que se proporcionó como parámetro.

    Por ejemplo, digamos que queremos seleccionar todos los elementos que usan la clase prueba:

    document.getElementsByClassName('prueba');

    También se pueden seleccionar múltiples clases, si deseara obtener los elementos que usan una clase jovenes y una clase adultos lo lograría utilizando solo la siguiente línea de código

    document.getElementsByClassName('jovenes adultos');

    Hagamos la cosas más interesantes,  le propongo una página con diferentes párrafos (<p>) pero solo aquellos que utilizan la clase contenido deben ser seleccionados para cambiar el tamaño de la fuente que usan. Para lograr tal objetivo podría hacer uso del siguiente código JavaScript:

    //se asignan todos los botones que permiten cambiar el tamaño de la fuente a variables
    var BotonFontSize1 = document.getElementById("btnFontSize1");
    var BotonFontSize2 = document.getElementById("btnFontSize2");
    var BotonFontSize3 = document.getElementById("btnFontSize3");
    var BotonFontSize4 = document.getElementById("btnFontSize4");
    
    //se vincula el evento click a cada botón
    BotonFontSize1.addEventListener('click', function(){
       CambiaTamano(10);
    }, false);
    BotonFontSize2.addEventListener('click', function(){
       CambiaTamano(12);
    }, false);
    BotonFontSize3.addEventListener('click', function(){
       CambiaTamano(14);
    }, false);
    BotonFontSize4.addEventListener('click', function(){
       CambiaTamano(17);
    }, false);
    
    //funcion que utiliza getElementsByClassName para buscar todos los elementos que usan la clase contenido y asignar el tamaño de fuente especificado según el botón presionado
    function CambiaTamano(size) {
       contenidos = document.getElementsByClassName("contenido");
       //alert(contenidos.length);
       contenidos[0].style.fontSize = size + "px";
       contenidos[1].style.fontSize = size + "px";
    }

    Para ver en funcionamiento este código puede visitar el siguiente enlace: ejemplo getElementsByClassName (botón “+” para ver el código completo incluyendo HTML y CSS).

    Sin duda esta mejora en JavaScript nos ahorra mucho código, si usted tiene algo de experiencia con JavaScript se dará cuenta de que existen varias maneras creativas de utilizar getElementsByClassName, experimente y sin duda encontrará muchas de ellas. Si desea ver la especificación oficial al respecto visite:  HTML5 – getElementsByClassName.

    Algunos enlaces de relacionados:

    10 CSS Selectors Que Hay Que Tener En Mente

    Document.getElementsByClassName() (Mozilla.org)

    HTML 5.1 2nd Edition

    HTML DOM getElementsByClassName() Method (W3Schools)

    Algunos libros de interés:

    Algunos buenos libros que pueden ser de su interés:

    No Comment
  • Flash VS HTML5

    Flash VS HTML5 (Parte 4)

    Que se pongan de pie todas las personas que alguna vez han querido ver algún video, y repentinamente hayan comentado algo como “oye, se escucha, pero no se ve”, y después de un rato de experimentar, preguntar e indagar llegan a la conclusión de que “falta el bendito codec”.

    Situaciones como estas existen prácticamente desde que la computadoras permiten ver video, pero en estos días este tema aflora con nueva fuerza,  debido al contexto del video en la Web dentro de la nueva especificación HTML5, que incluye el nuevo elemento <video>, el cual permite añadir este tipo de contenido fácilmente sin requerir plug-ins de terceros, como lo es el Flash Player entre otros.

    Diferencia entre FORMATO DE ARCHIVO DE VIDEO y CODEC.

    Primero aclararé un punto de confusión tremendamente común, siempre que puedo lo hago porque, de verdad, existe una graaaaan confusión al respecto entre los consumidores de video.

    Los formatos de archivo de video como .mov, .avi, .rm, .flv, etc., solo son el formato contenedor de la información de un video, pero este formato ¡NO es el codec ni de imagen, ni de audio para ver el video!. Para aclarar esto me auxilio constantemente del archivo de compresión .zip, si usted desea guardar cualquier tipo de archivo en en un formato de compresión como ZIP,  simplemente incluye este contenido dentro de un archivo con extensión .zip y no se preocupa si tal contenido son imágenes, archivos .doc, archivos .pdf o cualquier otra cosa. Cuando otra persona descomprime ese archivo .zip  puede obtener los archivos guardados dentro, y dependerá de si esta otra persona cuenta con Word para ver los archivos .doc, o Adobe Reader para ver archivos .pdf, de no contar con las herramientas necesarias para ver los archivos enviados dentro del archivo .zip no será posible verlos aunque cuente con los archivos completos y correctos.

    Hablando de video, el equivalente al archivo .zip son los archivos en formato avi, mov, flv, etc., estos son solo el formato del archivo contenedor, dentro se almacena información codifica para los cuadros que forman un video, y la información codificada que corresponde al audio, para decodificar esta información requerimos del codec apropiado. Si no contamos con los codecs indicados para el video y el audio, no será posible ver el video en cuestión correctamente aunque el video persé no tenga ningún problema, así como sucedería si no contamos con Word para ver el archivo .doc en el ejemplo del archivo .zip.

    La parte más inconveniente en lo que respecta al video en HTML5 es que estamos en medio de una nueva “guerra de navegadores” y los fabricantes no se han puesto de acuerdo acerca de cual deber ser el formato estándar para desplegar video y por lo tanto tampoco de cuales codecs deberían ser usados. Por lo que debemos estar pendientes de que navegador es compatible con que codecs de video (la wikipedia cuenta con una sección que se ha actualizado recurrentemente)

    ¿Cómo funciona?

    No describiré demasiado como insertar un video flash en una página, ya que dada la longeva presencia de flash existe una gran cantidad de recursos donde se enseña como hacer esto con gran detalle. La novedad por el momento recae más en la etiqueta <video> que busca trabajar casi con la misma facilidad con que lo hace la etiqueta <img>, el elemento video cuentan con varios atributos como src, control, autoplay, width, height, poster y otros más:

    <video src="video.mp4" width="360" height="240" controls="controls">
    </video>

    ¿Qué formato utilizar?

    No se cuenta aun con un formato universal e infalible para todos los navegadores, pero podemos utilizar múltiples formatos en la misma etiqueta video, en caso de que el navegador no reconozca un formato se irá al siguiente:

    <video controls width="350" height="250">
     <source src="video.ogv" type="video/ogg" />
     <source src="video.mp4" type="video/mp4" />
    </video>

    ¿Qué hacer si el navegador no soporta ningún formato?

    Si el navegador no soporta ninguno de los formatos que se han colocado siempre se puede colocar el video en formarto Flash y verlos de esa manera:

    <video controls width="350" height="250" >
        <source src="video.ogv" type="video/ogg" />
        <source src="video.mp4" type="video/mp4" />    
        

    http://player.swf?file=video.mp4

    
    </video>

    Al momento algunos navegadores responden mejor que otros al elemento video, y muchas personas utilizan navegadores viejos, para estos casos Flash es todavía una buena alternativa, aunque la tendencia parece indicar que el elemento video se consolidará cada vez más poco a poco.

    La comparación

    Cuando se trata de video, HTML5 en general tiene mejor rendimiento en términos de consumo de recursos y más fácil de implementar cuando hablamos de código, pero por el momento la distribución de Flash es mayor y funciona igual en todos los navegadores una vez que estos tienen el plug-in instalado. Flash tiene manejo de pantalla a tamaño completo, HTML5 no por el momento, aunque se sabe que se trabaja sobre ello. Flash soporta video en streaming, HTML5 lo hará en el futuro pero por ahora no lo puede hacer.

    Todas las desventajas del video en HTML5 sobre Flash parecen ser temporales y a esto se suma que Adobe anunció recientemente (Nov 2011), que ya no habrá desarrollo de Flash para móviles, veremos que pasa!

    Ir a parte 3       Ir a parte 5

    No Comment
  • Flash VS HTML5

    Flash VS HTML5 (Parte 3)

    Por alguna razón mucha gente buscamos que haya buenos y malos en muchas situaciones, casi sin cuestionamiento el títlo de bueno se le ha dado a HTML5, los malos Flash y Silverligth y si desea agregar el feo quizá una vez más Silverlight.

    La realidad es que no hay bandos reales, lo que tenemos son más opciones y eso es lo que hay que aprovechar. Por supuesto habrá situaciones donde hay que elegir, y para tomar decisiones hay que conocer algunas características de nuestras alternativas:

    Animación.

    Flash.

    Primero hay que estar al tanto que Flash nació como una herramienta de animación en un sentido más tradicional, la primera herramienta que creaba contenido Flash era un programa con herramientas del tipo “diseño gráfico” como líneas, círculos, rectángulos, bote de pintura, etc., y con una línea de tiempo para colocar las figuras dibujadas frame a frame y manipularlas de acuerdo a lo que se deseaba.

    Flash ha evolucionado y ya no cuenta con una sola herramienta para crear contenido, Flash ya no solo está orientado a sólo a hacer animaciones “artísticas o experimentales” si no que inclinado a ser un verdadero framework para crear aplicaciones conocidas como RIAs (Rich Internet Aplications), en estas puede combinar diferentes grados de animación.

    Ventajas:

    • Hacer y animar fluidamente dibujos de trazo libre es amable y fácil.
    • Hay una amplia comunidad desarrollo.
    • Existe mucha documentación libre y de pago.
    • Adobe está constantemente mejorando esta tecnología.
    • Los resultados visuales que se pueden obtener son realmente de muy alta calidad.

    Desventajas:

    • Se require de un plug-in de tercero instalado para ver contenido Flash.
    • La versión del plug-in puede ser un factor problemático para usuarios y desarrolladores.
    • El contenido Flash no es indexable, esto dificulta que los buscadores y otras herramientas  ubiquen, interpreten y clasifiquen su contenido.
    • Además  de conocer HTML, JavaScript, CSS, etc., hay que aprender ActionScript y múltiples herramientas para explotar verdaderamente el potencial de Flash.
    • Los elementos más interesantes de la plataforma Flash son propietarios, por lo tanto tienen costo.

    HTML5

    La animación en HTML5 cuenta con varias alternativas para ser creada, puede usar solo JavaScript y CSS3, puede utilizar el elemento Canvas o la tecnología SVG. Todos estas alternativas han sido creadas desde un punto de vista programático, es decir, siempre se pensó en crear animaciones utilizando código de programación y no una  herramienta de diseño con una interfaz de usuario.

    HTML5 se encuentra evolucionando rápidamente y mucha gente está prestando atención, la misma compañía dueña de Flash ha estado experimentando con las posibilidades de este nuevo estándar y proponiendo cosas, como la importación de contenido desde la aplicación Adobe Flash a HTML5, la creación de Adobe Edge (que si me preguntan es un intento de hacer de HTML5 lo que Flash fue originalmente) , entre otras cosas.

    Ventajas:

    • Todo es libre y gratuito.
    • No existe necesidad de utilizar plug-ins.
    • Una rápidamente creciente comunidad de desarrollo y documentación.
    • La indexación de contenido combinado con la fuerte semántica de HTML5 van de la mano de gran manera.

    Desventajas:

    • HTML5 no es lo más conveniente para la animación detallada y fluida (del tipo dibujo animado) por ahora.
    • HTML5 no es una especificación terminada, por lo que hay cosas que aún no están concluidas o son experimentales.
    • No todos los navegadores soportan todas las características de HTML5 o no las soportan de igual manera.
    • HTML5 no tiene aún buenas alternativas que sean amables con diseñadores gráficos.

    Cuando hablamos de animación, el consumo de recursos es un punto donde se critica mucho a Flash, pero tengo que admitir que Adobe se está esforzando mucho en este sentido y HTML5 aunque promete en este tema, tiene sus bemoles en ciertas circunstancias, habrá que esperar un poco para definir este punto con claridad.

    Conclusiones:

    Si desea hacer animaciones con trazos libres, que no requieren demasiada programación pero si mucho trabajo gráfico y deben ser de gran fluidez, mi recomendación es Flash.

    Si desea hacer aplicaciones de escritorio con moderado grado de animación y muy  buena presentación, considere utilizar AIR , si desea importar estas aplicaciones a la web o viceversa Flex es una buena opción (estas tecnologías son parte de la plataforma Flash).

    Si desea hacer aplicaciones web con moderado grado de animación y desea familiarizarse con los estándares del futuro vale la pena dedicarle tiempo a HTML5.

    Si el presupuesto es un problema, los estándares libres siempre son una interesante opción, es claro que HTML5 brilla en este caso.

    En la siguiente parte de esta serie de posts abordaré ventajas y desventaja de estas tecnologías desde el punto de vista de video.

    Ir a parte 2         Ir a parte 4

    No Comment
  • Flash VS HTML5

    Flash VS HTML5 (Parte 2)

    En la entrada anterior hablé de la tecnología Flash y un poco de su historia, con el fin de comprender mejor de que va Flash desde su inicio. Ahora le toca el turno al famoso y esperado HTML5. De unos dos años para acá se ha hecho mucho escándalo alrededor del flamante HTML5, y con razón, ya que presenta muchas nuevas y prometedoras características.

    He observado que muchas persona caen en una impresición similar a cuando se habla de Flash, es decir se habla de HTML5 como un todo, como una especie de entidad única que merodea en la Web creando páginas interesantes. La verdad es que HTML5 es algo que viene acompañado de varías tecnologías con las cuales se complementa para poder funcionar.

    HTML5 es únicamente la especificación más nueva, publicada por la W3C para HTML, el lenguaje base para crear páginas Web. La especificación define como deberían escribirse las etiquetas o tags que instancian un elemento HTML en nuestras páginas, que atributos y eventos poseen. Eso es todo, y lo más curios de todo es que ni siquiera es una especificación completa ni terminada, pero entonces ¿por qué tanto escándalo? :

    HTML5 es más rigorista.

    Anteriormente si se escribía una página HTML podía caer en errores de escritura, combinar mayúsculas y minúsculas en el código, no cerrar etiquetas que requerían cierre, ignorar tipos MIME, entre otras cosas de mal gusto para programadores exigentes, y las páginas en muchos casos aún se veían como se esperaba, haciéndonos olvidar todos los errores cometidos y creando malos hábitos. Para intentar solucionar esto se creó XHTML, pero nunca fue ciento por ciento adoptado por todos los desarrolladores. HTML5 intenta recuperar el espíritu de precisión de XHTML, mantener la familiaridad de HTML y unificarlo todo en la nueva especificación HTML5 (en el futuro crearé un post para hablar de XHTML2 y XHTML5 que tienen su historia, pero me lo guardo para no salir de contexto).

    El énfasis en la semántica en el código HTML es realmente notable e incluso abrumador cuando se comienza a desarrollar.

    Nuevas etiquetas para formularios.

    Tengo la impresión de que este punto no es muy mencionado pero a mi me parece importante porque puede ahorrar tiempo y costos. HTML5 incluye una nueva serie de etiquetas para colocar nuevos controles para formularios, por ejemplo, barras de progreso, campos de texto que filtran números y patrones, campos de texto que validan direcciones de correo y URLs, campos de texto que muestra color pickers y calendarios, entre otros más. Este tipo de controles requerían de programación y tiempo extra o incluso de comprar controles de terceros, pero HTML5 lo incluye de entrada.

    Nuevas etiquetas para contenido multimedia.

    Este aspecto en realidad al que la mayoría de la gente se refiere cuando habla de HTML5. La nueva especificación propone nuevas etiquetas para colocar audio y video de manera nativa sin el uso de plug-ins de terceros y/o propietarios, como justamente son el Flash Player o el reproductor de contenido Silverlight.

    Pone sobre la mesa el elemento Canvas, que es justamente uno de los recursos principales para crear animaciones con gráficos vectoriales e imágenes, sin embargo esto se hace hoy por hoy principalmente de manera programática, nótese esto porque será un punto importante para el encuentro mano a mano entre Flash y HTML5 para la tercera parte de la entrega de posts.

    CSS3 y JavaScript.

    Tecnologías sin las cuales HTML5 no podría hacer algo mínimamente  interesante  y que se encuetran evolucionando paralelamente al mismo HTML5. Esto es algo sumamente importante, ya que antes de alguien pueda pensar en que aprender HTML5 solo es conocer algunas etiquetas nuevas, la realidad es que si aspira a desarrollar con HTML5 debe aprender la nueva especificación para hojas de estilo nivel 3 o CSS3 y los nuevos recurso JavaScript. Combinando etiquetas HTML5, CSS3 y JavaScript se puede lograr una mucho mejor manipulación del aspecto y comportamiento de elementos HTML que nunca antes, logrando una mejor estética en nuestras páginas y en nuestro código al separar programación estructural de programación visual.

    Web sockets y Web workers.

    No hablaré mucho de esto, solo diré que aquellos gurús adentrados en programación con sockets y la programación por hilos tienen en HTML5 algo muy interesante por revisar.

    En la próxima entrada ¡comenzarán los verdaderos golpes!

    Ir a parte 1            Ir a parte 3

    No Comment
  • Flash VS HTML5

    Flash VS HTML5 (Parte 1)

    No se trata de una guerra, ni de una pelea, de hecho consideré titular esta entrada como Flash y HTML5 pero me pareció que el “versus” sería más provocador para los “fanboys“.  Personalmente creo que Flash se ha ganado el lugar que tiene en la Web, pero esto no quiere decir que siempre estará ahí, que siempre será la mejor o la única opción.

    Últimamente de manera continua algunas personas, que comienzan a desarrollar,  me han preguntado que es mejor y al mismo tiempo me he dado cuenta de algunas confusiones en el tema, de manera que decidí hacer una serie posts abordando el asunto y  esperando despejar algunas dudas a quienes desean desarrollar con estas tecnologías.

    Flash:

    Aveces se menciona a Flash como un todo, pero en realidad hay varias partes involucradas. Flash surgió como una tecnología  propuesta por la compañía Macromedia a finales de los 90s, que permitía desplegar gráficos vectoriales en páginas Web, Flash consta básicamente de un plug-in instalado en el navegador de un usuario que permite el despliegue de contenido elaborado en este formato, a esto se le conoce como Flash Player. Al mismo tiempo que Flash Player Macromedia creó la herramienta con la que originalmente se podía crear este tipo de contenido, esta herramienta fue concebida como un software de animación para crear contenido destinado principalmente a la Web, este software se le llamaba simplemente Flash.

    El Flash y el Flash Player han ido evolucionando lo largo de los años, durante este tiempo Macromedia liberó parte de su tecnología para permitir a terceros crear contenido SWF (el formato que comprende Flash Player), e esto se agregó la posibilidad de incluir video en formato FLV el cuál también se visualiza gracias a Flash Player. Otra parte importante de Flash es su script de desarrollo conocido como ActionScript el cuál también ha tenido cambios importantes.

    En 2005 la compañía Adobe (dueños de Photoshop) adquiere a Macromedia, con esto también vinieron cambios sobre Flash, la herramienta de autoría ahora se conoce como Adobe Flash Professional y surge también la nueva versión de su script el popular ActionScript3, el cuál introduce al desarrollo con Flash verdadera programación orientada a objetos.

    Una de las mayores limitantes de Flash ha sido su pobre interacción con datos y su poco practicidad para crear aplicaciones que buscaban más productividad y un tanto menos de animación como tal, manteniéndose aún sobre la Web pero considerando  también aplicaciones de escritorio. Adobe consciente de esto crea Flex y AIR, un conjunto de tecnologías que también crean contenido Flash pero con mejores capacidades en cuanto al desarrollo con el manejo de datos, y más orientada al desarrollo tradicional de aplicaciones.

    Las  grandes desventajas de las tecnologías basadas en Flash siempre han estado relacionadas con el rendimiento en general, el consumos de recursos y algunos temas de seguridad. Factores que hay que considerar antes de crear una aplicación.

    En la siguiente parte de esta entrada abordaré al novedoso HTML5…..

    Ir a parte 2

    1 Comment