Autor:

  • El problema de la educación

    La reflexión

    Hoy en día muchos de nosotros ya conocemos la triste situación en la que se encuentra la educación básica en muchos países del mundo, particularmente en los países de América Latina, varios de nosotros hemos sufrido los pesares causados por sindicatos ventajosos y corruptos que tienen en sus filas a maestros malos, pseudomaestros, o incluso buenos maestros que se ven atrapados en circunstancias imposibles. Todo esto es desde luego grave, pero creo que estamos más que diagnosticados de lo mala que es nuestra situación a nivel de educación básica, puede echar un vistazo a documentales como De Panzazo o Waiting for Superman que abordan el tema respecto a México y Estados Unidos respectivamente, aunque usted no viva en ninguno de estos países puede que encuentre puntos en común con estos casos.

    Pero…¿que pasa en la educación superior?, todos hemos escuchado de profesionales que terminan conduciendo un taxi o haciendo hamburguesas, y no es que ser taxista o voltear hamburguesas tenga algo de malo o indigno, es simplemente que ser taxista o cocinero no es el objetivo de invertir 4 o 5 años de la vida de un individuo, ni por supuesto tampoco el de los gastos y esfuerzos familiares y gubernamentales que el paso de una persona por una institución de nivel superior implican. Entonces, ¿qué diablos pasa? ¿por qué sucede esto?…me he encontrado que la mayoría de la gente argumenta que el respectivo gobierno “no genera los puestos de trabajo necesarios”, creo que esta afirmación tiene su cuota de verdad, sin embargo esa no es la única razón ni la más exacta, le propongo algunas reflexiones más que quizá saltan menos a la vista pero están ahí:

    La actualización de planes de estudio y sus contenidos es demasiado lenta.

    Si me permite, ejemplificaré con una experiencia personal. Mis años de universidad se ubicaron entre los años 1995 y 2000, años que coincidieron con el gran ¡boom! de Internet, en esos momentos el plan de estudios de mi carrera (Ingeniería en Sistemas Computacionales) tenía lo que llamaban en mi universidad “tronco común”, lo que significaba en términos generales, que compartía asignaturas comunes con estudiantes de otras ingenierías, es decir, los estudiantes de Ingeniería en Sistemas en mi universidad debían cursar y aprobar obligatoriamente asignaturas como Estática, Dinámica, Termodinámica entre otras. Mi alma mater en esos años contaba con la llamada “Biblioteca de Ciencias”, que a pesar del pretencioso nombre,  no era nada más que una pequeña biblioteca que además de algunos libros, contaba con una red de más o menos 30 computadoras conectadas a Internet, a lo que se sumaban recursos almacenados en algunas decenas discos compactos, que debo reconocer que en esos años, y considerando que hablamos de una universidad mexicana, todo eso era TODO un privilegio, ya que fue la primera universidad con algo así en toda América Latina.

    Descrito el escenario, le expongo la realidad con la que me he enfrenté, gran parte de esas materias de tronco común orientadas más a Ingeniería Mecánica, no solo nunca me han sido prácticas en lo que respecta a la Ingeniería en en Sistemas, si no que interferían con lo que realmente estaba aprendiendo gracias a la infraestructura universitaria, es decir, en esos años gracias al acceso a Internet y a algunas buenas amistades, yo ya estaba aprendiendo lo que eran los navegadores y su funcionamiento, como se construían las páginas, comencé a aprender HTML, aprendí lo que eran formatos de compresión de imágenes y audio, tuve mis primeros contactos con Flash y su ActionScript entre muchas otras cosas, todo era realmente nuevo y básico, pero sumamente interesante para mi.

    Desafortunadamente mi desempeño académico nunca se vio evaluado con respecto a esto, pero sí por la resolución de problemas de termodinámica, estática, dinámica y otros, que honestamente solo despertaban mi curiosidad de vez en cuando, ya que esos problemas de física aplicada, ante mis ojos, palidecían a lado de hacer un programa capaz de enviar un archivo de un lugar del mundo a otro, o de combinar mi gusto por el dibujo con programas gráficos y código de programación. El resultado al final fue que mis siempre buenas notas hasta el momento, se convirtieron en notas más bien mediocres y a veces malas, poca gente más allá de un par de amigos, sabían o notaban mis pequeños pero constantes progresos en el uso del extraño HTML, en el uso de nuevos paquetes gráficos, y en otras curiosidades del momento. Muy pocos profesores y estudiantes se daban cuenta de la revolución que estaba teniendo lugar debajo de nuestra nariz, ya que nadie en ese momento me dijo que a pesar de todo, lo que estaba aprendiendo se convertiría en el pilar de toda mi etapa laboral y profesional hasta el día de hoy.
    La moraleja de la historia es que las instituciones de educación superior, deben de estar mucho más enteradas de lo que realmente está pasando en el mundo y deben adaptarse rápidamente a el, más aun cuando nos referimos a carreras de ciencias aplicadas. Los giros de timón que se están dando en las industrias existentes, y la velocidad con la que aparecen nuevos mercados y oportunidades se miden en meses y semanas, mucho de lo que enseñan las universidades NO SIRVE si tardan 1, 2 o 3 años en actualizarlo, y suman aun más tiempo decidiendo si lo hacen o no, el resultado será una falta de competitividad tremenda.

    Falta de visión por parte de instituciones, estudiantes y profesores.

    Tenemos una variedad de factores que causan situaciones difíciles de sortear, por un lado sin duda existen las crisis económicas regionales, nacionales y mundiales, la falta de incentivos gubernamentales y los indices de corrupción (inserte su indice de corrupción nacional aquí), pero quizá lo más grave que padecemos en muchas partes del mundo, en especial en América Latina, es la falta de visión. Muchos estudiantes hoy en día siguen teniendo una perspectiva en la que deben cumplir con los requisitos que solicita hoy una institución de nivel superior para graduarse, bajo esta idea, una vez graduados eventualmente una empresa o institución los contrataría con un sueldo “razonable” y así podrían hacer carrera dentro de esa misma empresa o institución, donde ascenderían poco a poco; lamento decirle a todos aquel que aun cree eso, que hoy en día, los casos así son MUY POCOS, esas situaciones quizá fueron más comunes, apróximadamente, de los años 80s hacia atrás (al menos en lo países con mínima estabilidad), pero esa situación ya NO es la realidad más dominante el día de hoy. Por otra parte tenemos a los profesores, estos sin duda son algo importante y necesario, pero ¿cuáles son las razones por las que un profesor imparte cátedra en este momento?, en los casos más benignos, tenemos a los profesores que dan clase por legítima vocación, tenemos a aquellos que  gustan de compartir su experiencia y conocimiento de campo pero que al mismo tiempo ejercen su profesión de manera paralela; la parte poco conveniente son sin embargo, los casos en que los profesores que ofrecen clases hoy en día lo hacen porque no encuentran (o no buscan) una mejor opción, porque no les gusta asumir riesgos y algún amigo o pariente encontró manera de ofrecerles un puesto humilde pero seguro, o porque simplemente no les interesa ejercer. Me da la impresión de que la mezcla de todas estas situaciones han hecho que nos olvidemos de los principales objetivos que debemos alcanzar.

    El OBJETIVO PRINCIPAL de la educación superior NO es convertir a sus alumnos en maestros de sus propias aulas, tampoco en graduar a gente que se dedicará a actividades completamente ajenas a sus estudios, el PRINCIPAL OBJETIVO es preparar a personas para poder CREAR Y MEJORAR bienes y/o servicios, ya sean materiales o intelectuales, que colaboren al desarrollo de su sociedad vía el uso de sus conocimientos. Para terminar este punto permita hacerle algunas preguntas, ¿qué es lo que pretende verdaderamente usted, su escuela y sus profesores, haciendo lo que hacen actualmente?,¿cuántos de sus compañeros o profesores están intentando inventar algo nuevo?,¿cuántos intentan mejorar alguna práctica o proceso?,¿cuántos están intentando crear una empresa?,¿cuántos están intentando registrar una patente?

    Creación, derechos y patentes.

    Esto está muy relacionado con el punto anterior, pero ahora me refiero no solo a las personas que actualmente están activas dentro de los sistemas educativos sino también a los que ya somos fruto de ellos. A muchos países nos falta crear, crear en todo el sentido de la palabra. Como mencionaba al principio de esta entrada, escucho continuamente a muchas personas de diferentes nacionalidades decir la frase “es que el gobierno no crea los empleos suficientes“, personalmente creo que esa postura es inexacta, los gobiernos son responsables de GENERAR LAS CONDICIONES ADECUADAS para crear empleos, pero no son directamente responsable de crear el empleo per se. Lo explico mejor, si deseamos que una empresa nos contrate, primero alguien debe crear esa empresa, y una empresa se crea en función de algún producto o algún servicio. Posiblemente ya puede ver a donde voy, en efecto los gobiernos deben fomentar la creación de empresas (¿qué tan bien lo hacen?…ese es otro asunto), pero los gobiernos muy rara vez innovan nuevos productos o nuevos procesos, proporciona las reglas para que una empresa entre a un mercado y ayudan a regular al mismo, pero, ¿qué pasa si nosotros las personas simplemente no creamos nada, ni la idea, ni la tecnología, ni el servicio, ni el producto? la respuesta es simple, ninguna empresa nacerá sin algo de eso, la cadena simplemente se rompe desde su primer eslabón; si eso sucede entonces una comunidad queda a expensas de unas pocas empresas (continuamente nacidas en otro lugar), y a que estas quieran tener presencia en nuestra comunidad, las personas que viven ahí solo puedan a aspirar a los puestos que estas deseen ofrecer, a veces estas empresas caen en cuenta de que se vuelven tan importantes para la economía de esa comunidad, que debido a la falta de creación de competencia, comienzan a presionar al respectivo gobierno para tener mayores privilegios, de lo contrario se van ¿Le suena esto conocido?. En fin, si no mantenemos un índice aceptable de creación, innovación, y por lo tanto competitividad, podemos crear círculos viciosos que bien podrían ser virtuosos.

    Y no solamente es crear algo, también hay que aprender como proteger y fomentar la creación, aunque actualmente las formas de hacerlo son polémicas no sobra aprender y enseñar un poco sobre derechos de autor, registro de marcas y patentes. Mucha gente tiene variados e interesantes puntos a favor y en contra respecto a las patentes, pero el hecho es que hoy por hoy son un indicador bastante bueno del estado económico y el nivel de vida de país. Si desea dar un vistazo a algunos de los resultados de los últimos estudios publicados por la World Intellectual Property Organization para averiguar como están las cosas en su país, le comparto los siguientes enlaces:

    http://www.wipo.int/export/sites/www/freepublications/en/economics/gii_2012.pdf

    http://www.wipo.int/ipstats/es/statistics/country_profile/

    http://www.wipo.int/ipstats/en/wipi/figures.html

    Ni son todos los que están, ni están todos los que son.

    A lo largo de mi carrera me he encontrado con personas que están más que calificadas para hacer un trabajo de nivel profesional pero no cuentan con educación formal, tristemente también con muchos que cuentan con todas las credenciales de nivel licenciatura, maestría y doctorado, pero en la práctica no cuentan ni con las mínimas habilidades para solucionar problemáticas apropiadas para las habilidades que presumen sus títulos. También podemos hablar de las personas que abandonan sus carreras porque descubren que disfrutan o hacen mejor otra cosa, o simplemente no les gusta lo que estudiaron.

    Esto indica desde luego, que existe un gran problema en nuestros sistemas educativos básicos y de nivel superior, que está alejando a las personas con habilidades, vocación o talento de la educación formal, o quizá están ubicándolas erróneamente o dejando pasar a demasiadas “poco adecuadas”, lo que no sería tan grave de no ser porque todo eso significa que se le quitó la oportunidad a alguien que la hubeira aprovechado mejor y que no se hubieran desperdiciado recursos que probablemente ya no se recuperarán. Podríamos pensar que esto es caso del tercer mundo, pero no es así, también en lo países desarrollados sucede, vamos a ahorrarnos los casos malos y pensemos en algunos casos famosos y positivos, tenemos que el fundador de Microsoft, Bill Gates, dejó su carrera universitaria truncada, el caso en que Steve Jobs fundador de Apple también abandonó la universidad, un caso más actual es Mark Suckerberg fundador de Facebook, que al igual que los anteriores dejó de lado su carrera universitaria.

    Me parece que los expertos tienen cosas por analizar sobre este punto.

    Conclusión.

    Hay muchos retos nuevos ante nosotros actualmente, y las colegios superiores han logrado mucho, tienen muchas cosas buenas y sin duda son un baluarte de la educación y de las sociedades modernas en general, pero al igual que todas las cosas vivas que buscan sobrevivir, deben saber trasformarse y reinventarse para poder hacer frente a esos nuevos escenarios, los cuales exigen nuevas formas en el pensar y en el actuar para poder enfrentarlos con prontitud y eficacia.

    Lo dejo con uno de los videos más reveladores que he visto en Internet en su versión para el 2011:

    2 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
  • Redes Sociales Politica

    Tecnología, Redes Sociales y Política

    Si lee esta entrada probablemente tenga más sentido para usted la advertencia de Mafalda del gran Quino 🙂 .

    En este blog siempre se usa a la tecnología como la mina que se explota para todo contenido y ahora toca el turno de abordar como aplica o se une esta a algo que está siempre afectándonos, la política, se que para muchos de los lectores con el perfil para leer este tipo de blogs la política es un tema que quizá prefieren no tratar, pero en estos tiempos donde en varios países se está en víspera de elecciones, la tecnología y concretamente la que se refiere a las redes sociales, nos pone en otro contexto que vale la pena analizar un poco.

    El potencial.

    Muchas industrias e individuos han caído en cuenta de que las redes sociales, debido a su gran alcance, pueden ser una gran herramienta para colocar su servicio, producto, marca o simplemente una idea, a consideración de una mayor cantidad de personas. Las fuerzas políticas de todo el mundo no son ajenas a ello, por lo que ahora tanto partidos, candidatos, políticos de todos los niveles, grupos de poder económico y financiero ya utilizan de manera constante las posibilidades de estas nuevas formas de comunicación, promoción e influencia.

    Por otro parte, los ciudadanos comunes y corrientes, ahora podemos interactuar más directamente con todas las entidades que utilizan estos medios, acreditándoles, criticándoles o exigiéndoles, situación que sin duda crea la posibilidad de empoderar más al ciudadano cuando se trata de situaciones políticas. Pero no podemos negar que en el otro filo de la navaja, tenemos a las personas menos informadas y con menor capacidad crítica que sin duda serán víctimas de información falsa.

    Hasta el momento quizá los casos más emblemáticos del potencial de las redes sociales, desde un punto de vista político, han sido en Estados Unidos con una notable y hábil campaña en redes sociales por parte del partido demócrata y el entonces candidato Barak Obama, tenemos al famoso (o infame) Donald Trump que supo alcanzar un nicho de personas que lo apoyaron hasta ganar la presidencia, en Egipto con una serie de protestas organizadas en gran parte con la utilización de redes sociales y Siria donde al igual que en Egipto las redes sociales tomaron un rol importante al momento de formar comunidades y convocar movimientos, y así podemos continuar con muchos otros casos más que han sucedido en todo el mundo, como por ejemplo en Inglaterra donde se organizaron protestas con el uso de redes sociales y donde además destacó el eficiente y seguro sistema de mensajería de BlackBerry para sus teléfonos inteligentes, lo que puso a lo compañía en una situación “incomoda” frente al gobierno Inglés.

    Lo medios tradicionales como la radio y la TV se han visto sumament golpeados por las nuevas tecnologáis de comunicación, en mi país México, los grandes corporativos de esta industria no han logrado renovarse eficientemente para mantener el fugaz interés de las nuevas generaciones, perdiendo así grandes cantidades de audiencia (e influencia). Lo cual creo que eventualmente los tendrá que llevar al camino de la innovación y la mejora de sus contenidos si es que no quieren desaparecer.

    El mal uso.

    Todas las herramientas creadas por el ser humano han sido utilizadas con fines productivos pero sin duda también con fines negativos, destructivos o simplemente estúpidos, desafortunadamente las redes sociales no han sido la excepción. En mi país, por ejemplo, estamos en constante bombardeo de propaganda política que se agudiza en tiempo electorales, lo cual me ha permitido ver que tan mal podemos utilizar la redes sociales tanto las fuerzas políticas como los cuidadanos:

    Las fuerzas políticas oficiales. Partidos, candidatos, miembros de campañas, organizaciones, sindicatos, etc., siguen creyendo que las mismas malas prácticas del “mundo real” se aplican y funcionan igual en el “mundo digital” lo cual en varios casos es totalmente falso. Las redes sociales atacan muchos nichos diferentes, es decir, contienen diferentes tipos de usuarios pero que tienen algún “perfil” común, por lo que mientras que en el “mundo real” quizá puede servir llevar cierto número de “acarreados” entre meeting y meeting, en Twitter, por ejemplo, no tendrá el mismo efecto conseguir cierto número de seguidores artificiales (o acarreados digitales) entre twit y twit. Tener un millón de likes no es necesariamente más impresionante que tener 100 para los que mejor entienden una red social en línea. Muchos políticos, candidatos y sus coordinadores de redes sociales parecen pensar que estas son unidireccionales, como la TV o la radio, y no se han dado cuenta que la riqueza de estas nuevas plataformas es la interactividad con las personas, es decir solo escriben una serie de enunciados pero muchas veces no conversan ni con sus propios seguidores de manera productiva, lo cual los reduce al nivel de vulgares spammers. O bien, si menciona a cualquier candidato en un tono crítico se verá bombardeado por una seria de bots o perfiles pagados para desacreditar o ensalsar su comentario.

    Poderes fácticos. No es ningún secreto que estamos rodeados de influencias ajenas a nuestro gobiernos y nuestros territorios. Personas y grupos con agendas e intereses particulares observan y manipulan muchos ejes de poder, y las nuevas tecnologías también son utilizadas para estos fines. No tenga la menor duda que esas influencias poco o nada transparentes tocarán la pantalla de su dispositivo en cualquier momento (si no es que ya lo hicieron).

    La ciudadanía. Nosotros las personas de a pie, no libres de pecado, caemos en muchísimos malos vicios que no nos dejan aprovechar el potencial de las redes sociales, hoy en día las personas que tienen acceso a estas herramientas tienen la posibilidad de cuestionar, exigir, indagar y ser escuchadas quizá como nunca antes en la historia humana, pese a esto seguimos atrapados en discusiones aldeanas (cómo las que ocasiona cualquier troll) tan malas y pobres como las de muchos candidatos y funcionarios políticos (a veces peores), un ejemplo concreto en México, entre usuarios regulares de redes sociales, no he visto una sola discusión seria y real acerca de sus candidatos (quizá ha sido mi suerte), la mayor parte de los comentarios se reducen a temas tales como las medidas de una edecán en un debate, insultos casi automáticos o amenazas de muerte de un usuario a otro por expresarse de algún modo, un sin fin de memes chistosos y ocurrentes pero irrelevantes acerca de cualquier tema político, y no es que esté mal ver el lado chusco de la política o tener pasión en una discusión, pero no es lo único ni lo más importante, hay que aprender a cuestionarlo todo de manera productiva.

    Información y tecnología.

    Se dice que Francis Bacon, un político, filósofo y artista inglés que vivió en el siglo diecisiete, acuñó la frase “información es poder“, lo cual no podría ser más cierto, por lo tanto, aquel que invierta más en conocer será el que tenga más oportunidad de salir mejor librado de engaños y problemas; el inteligente uso de todas las tecnologías que tengamos a nuestro alcance, como lo son las redes sociales, el teléfono inteligente, la computadora personal, la Internet, etc., hará de estas, la fuente de donde obtendremos cada vez más información hoy en día y en el futuro cercano…hagamos mejor uso de ellas.

    Algunos libros recomendables para saber más:

    2 Comments
  • 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
  • Visita a la Universidad Tecnológica de Tula Tepeji

    Hace poco menos de un mes (Marzo 2012) tuve la oportunidad de ser invitado a participar en las conferencias realizadas en la Universidad Tecnológica de Tula Tepeji con motivo de su 2da. Jornada de Tecnologías de Información, en tal evento disfruté el poder platicar con estudiantes y profesores acerca de HTML5 y otras tecnologías.

    Deseo agradecer a estudiantes, organizadores y profesores de este instituto por su invitación a este evento y permitirme conocer su agradable campus, a su comunidad y  un poco (en el poco tiempo disponible)  de conocer también lo bonito que es Tula en el estado de Hidalgo. Sin más agradezco de nuevo a la Universidad Tecnológica de Tula Tepeji por sus atenciones y a Alfaomega Grupo Editor por permitirme estar ahí.

    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
  • El caso Megaupload…la otra postura

    Sin duda en los últimos meses una  de las situaciones más sonadas en el mundo de la tecnología ha sido el caso Megaupload, para los que no sepan que es Megaupload (si es posible que exista alguien), es (o fue) uno de los servicios de alojamiento de archivos más populares. Megaupload inició operaciones en el 2005 y fue cerrado en Enero del 2012 por el FBI por presunta violación de derechos de autor.

    El caso Megaupload se suma como otro elemento a la ya encendida discusión que involucra temas como derechos de autor, piratería, prácticas desleales, monopolios,  modelos de negocios viejos y nuevos, iniciativas de ley y acuerdos como SOPA y ACTA entre otras. ¿Por qué seguir hablando de esto?  las respuestas a esta pregunta pueden ser muchas, pero en mi opinión (si a alguien le interesa), es que se debe seguir hablando de esto, porque los casos como este sentarán precedente y determinarán como trabajaremos, como consumiremos, como y que aprenderemos y en definitiva como viviremos en el futuro cercano, quizá suene dramático, pero creo que grandes fortunas y dominios terminarán y otros nacerán.

    Es verdad que no podemos pecar de ingenuos y decir que Megaupload no alojaba archivos ilegales siendo al mismo tiempo una herramienta útil para su distribución, ni tampoco se puede decir que el Sr. Kim Dotcom siempre ha sido una pera en  dulce,  pero vaya que en esta entrevista pone sobre la mesa algunas opiniones y afirmaciones  que pueden resultar incomodas e impopulares para gran parte de la industria establecida, pero también pueden ser ciertas en varios casos….por supuesto la mejor opinión es la que usted se forme.

    Personalmente me parece que la mayor parte de las noticias que se ven en medios tradicionales denotan cierto sesgo en este emblemático caso (claro, podría equivocarme), lo lamentable es que muchas personas y medios olvidan que también es importante presentar la otra versión, la del acusado, y que este se puede defender, así todos podemos tener una visión más amplia de lo que sucede alrededor, por lo tanto le presento a usted la interesante entrevistas hecha al polémico Kim Dotcom por John Campbell para el servicio de noticias de Nueva Zelanda 3 News hace un par de semanas.

    La traducción al español de esta entrevista se encuentra debajo del video, si encuentra algún error agradeceré si me lo hace saber, sin más:

    Kim Dotcom: Bueno, ya sabes, es un poco como una pesadilla, yo diría. Inesperado, terrible para mi familia, mi esposa que está embarazada de gemelos tiene pesadillas y se siente miserable. Por supuesto que estoy enfrentando una situación muy interesante.

    John Campbell: Kim, dices que fue inesperado. ¿Fue total y absolutamente inesperad0, nunca pensaste que esto pasaría en algún lugar del mundo en algún momento?

    Kim Dotcom: Bueno, el negocio tiene siete años. Hemos sido demandados sólo una vez, no por ninguna productora de cine o una empresa grande de contenidos, hemos gastado millones de dólares en asesoramiento legal en los últimos años y ellos siempre nos dijeron que estábamos seguros y que estábamos protegidos por la DMCA la cual es una ley en los EU que está protegiendo a los proveedores de servicios en línea de la responsabilidad por las acciones de sus usuarios, por lo que fue totalmente inesperado.

    John Campbell: ¿Qué te dijeron tus abogados acerca de lo que estabas haciendo? Como entendemos Megaupload, en sus términos más sencillos, es una especie gigante de sistema de intercambio en la nube, ¿cierto? Así que alguien sube algo, alguien lo descarga, estás compartiendo archivos, esos archivos pueden ser cualquier cosa, ¿verdad? ¿cómo protegerse contra las violaciones de los derechos de autor por las personas que utilizan Megaupload?

    Kim Dotcom: Bueno, supuestamente, y lo que todo el mundo creía, es que la ley nos protegía. No podemos ser responsables de los actos de terceros, mientras seguimos un régimen de eliminar las cosas que nos reportaban, cosa que hemos hecho durante todos estos años, estamos protegidos de acuerdo con la ley. Me resulta muy sorprendente que esto está sucediendo porque, como te dije, teníamos  un aviso legal todos estos años que decía que somos un proveedor de servicios en línea y no nos hacemos responsables por las acciones de terceros.

    John Campbell: ¿De dónde provienen Megaupload? ¿Cuál era la idea detrás de esto? Fue su idea, cierto, ¿por qué?

    Kim Dotcom: Bueno, un día un amigo me iba a enviar un archivo por correo electrónico y recibió un mensaje que el archivo es demasiado grande y el servidor de correo se había negado a enviarlo, así que pensé, ¿qué puedo hacer para solucionar eso? Así que, básicamente, cree un servidor en el que podía cargar un archivo y tenía un enlace exclusivo que luego le enviaba por correo electrónico a mi amigo para que pudiera obtener el archivo, y así es como Megaupload se inició, era sólo una solución a un problema que todavía existe hoy en día.

    John Campbell: ¿Qué tan rápido despegó, te sorprendió?

    Kim Dotcom: Bueno, me sorprendió la rapidez con que despegó, creció de forma viral, porque cada vez que alguien iba a subir un archivo a Megaupload para enviarlo a otra persona, esa persona conocería acerca de Megaupload y así todo mundo lo usaría porque era una herramienta tan útil… y gratis.

    John Campbell: Kevin Suh, vicepresidente senior de protección de contenido en la Asociación Cinematográfica de Estados Unidos, dijo, y cito, “Tú eres el mayor infractor de derechos de autor en el mundo”. ¿Es usted?

    Kim Dotcom: No, en absoluto. No soy un infractor de derechos de autor. Quiero decir, usted tiene que mirar a Megaupload en su tamaño. Estamos hablando de una red que se ejecuta en 1.5 terabytes de ancho de banda.

    John Campbell: Explícame ¿qué tan grande que es eso?

    Kim Dotcom: Eso es cerca de 800 transferencias de archivos que terminan cada segundo. Somos una empresa relativamente pequeña, no se puede esperar de nosotros para vigilar ese tipo de tráfico.

    John Campbell: Así que 800 transferencias de archivos se producen cada segundo.

    Kim Dotcom: Sí.

    John Campbell: 24 horas del día, todos los días del año.

    Kim Dotcom: Sí.

    John Campbell: Cada segundo.

    Kim Dotcom: Sí.

    John Campbell: ¿Y sabes lo que hay en las transferencias de archivos? ¿Eres capaz de mirar esos 800 archivos por segundo y decirlo?

    Kim Dotcom: Bueno, hay otras leyes que protegen a los usuarios y esas son las leyes de privacidad. Por ejemplo, en los EUA es la Ley de Comunicación de Privacidad Electrónica, que nos impide mirar en las cuentas de los usuarios de forma proactiva y buscar las cosas. Es como el correo electrónico, que es privado, no podemos ir allí y vigilar lo que estos usuarios están subiendo. Pero por eso tenemos nuestros propios términos de servicio en el que les decimos a nuestros usuarios, “No se puede cargar cualquier cosa que se esté infringiendo los derechos de nadie, sólo se pueden cargar las cosas que les pertenecen, y antes de que cualquier usuario suba un archivo a Megaupload tienen que seleccionar la casilla que dice “Acepto los términos del servicio”. Así que tenemos un acuerdo legalmente con estos usuarios en el que se supone que para no pueden subir cosas o archivos que no les pertenecen.

    John Campbell: Por supuesto, eso es una idea romántica, sin embargo, ¿no es así, que el hecho de marcar la casilla aceptando las condiciones de servicio, no quiere decir que vamos a comportarnos de esa manera cuando estamos allí, ¿verdad? Eso, quiero decir, debes haber sabido que la gente estaba haciendo lo que quería, una vez que entraba por la puerta principal. Ellos estaban intercambiando todo tipo de archivos que querían intercambiar. ¿Qué oportunidad se tenía de vigilar eso?

    Kim Dotcom: Bueno, por supuesto todo el mundo sabe que Internet está siendo utilizado para usos legítimos e ilegítimos. Creo que cada proveedor de servicios en línea tiene los mismos retos que tenemos. YouTube, Google, todo el mundo está en el mismo barco. Así que lo que hay que entender aquí es que le hemos proporcionado los propietarios de contenido la oportunidad de eliminar los enlaces que se infrinjan sus derechos. Por lo tanto, no sólo tenían un formulario en línea donde podían dar de baja enlaces que infringían sus derechos, tuvieron acceso directo a nuestros servidores por lo que podían acceder a nuestro sistema y eliminar cualquier enlace que encontraran en en Internet. Tuvieron acceso pleno y estamos hablando de 180 socios, entre ellos todos los estudios de cine importantes, incluyendo Microsoft y todos los grandes productores de contenido y que han utilizado este sistema en gran medida. Tienes que entender que ese sistema no era ni siquiera algo que era requerido por la ley. Nosotros, siempre lo ofrecimos voluntariamente, ellos removieron más de 15 millones de enlaces.

    John Campbell: Así que todos los miembros de la Motion Picture Association, todos los estudios de cine que son miembros de la Asociación Cinematográfica de Estados Unidos tuvo acceso directo a Megaupload.com para eliminar el material protegido por propiedad intelectual – es ese el caso?

    Kim Dotcom: Por supuesto.

    John Campbell: Y sin embargo, la acusación del FBI en contra tuya afirma, y cito, “infracción de copyright en una escala masiva con el daño estimado a los titulares de derechos de autor muy por encima de 500 millones de dólares de Estados Unidos”.

    Kim Dotcom: Bueno, eso es una completa tontería. Si lees la acusación y si escuchas lo que la Fiscalía ha dicho en la corte, por lo menos 500 millones de dólares los daños eran sólo de archivos de música y sólo dentro de un plazo de dos semanas. Así que en realidad están hablando de 13 mil millones dólares americanos, daño dentro de un año sólo para descargas de música. Toda la industria de la música de EUA está valorada en menos de $ 20 mil millones. Entonces, ¿cómo puede un sitio web ser el responsable de esta cantidad de daño, es totalmente alucinante y poco realista.

    John Campbell: ¿Así que realmente lo que sugieres  es que eres algún tipo de chivo expiatorio?

    Kim Dotcom: Bueno, no hay otra explicación para mí, porque no he hecho nada malo. No soy un criminal, este sitio web no ha sido creado para ser un paraíso de la piratería. Si nos fijamos en los comentarios por ahí y la discusión que está pasando en línea, eso es lo que todo el mundo siente. Es una locura.

    John Campbell: Debido a que el FBI y las personas que quieren llevarnos a juicio alegan, y han utilizado estas palabras, que no tienen precedentes. Que la escala de la piratería no tiene precedentes. Nunca ha habido nada como esto antes en la historia humana, que eres el pirata que vence a todos los piratas.

    Kim Dotcom: Sí. Es un poco como la arma de destrucción masiva en Irak. Si quieres ir detrás de alguien, y tienes un objetivo político vas a decir lo que sea necesario. Estas son mentiras y mentiras. Hay un centenar de empresas que hay por ahí que ofrecen el mismo servicio como nosotros. ¿Por qué no le ha ocurrido algo a ellos?

    John Campbell: ¿Me puedes dar un nombre? Sólo el nombre de … ¿me puedes dar un par de nombres?

    Kim Dotcom: Muchos sitios de web. Mediafire. Tiene base en los EUA, y ofrece exactamente el mismo servicio que nosotros.

    John Campbell: ¿La opción de intercambiar archivos?

    Kim Dotcom: Sí. Rapidshare, Fileserve, Filesonic. Microsoft tiene su propio servicio en la nuble, Skydrive. Google ha lanzado un nuevo servicio llamado Drive. Todo el mundo que está en el área de la nube, en el mismo negocio, tienen los mismos problemas que hemos tenido nosotros luchando contra la piratería. Pero nosotros no somos responsables del problema y esto es, creo, lo que cada uno tiene que entender. ¿De dónde proviene de la piratería? La piratería viene, tu sabes, de la gente, digamos, en Europa que no tienen acceso a las películas al mismo tiempo que se liberan en los EUA. Este es un problema que ha nacido dentro de este modelo de concesión de licencias y el viejo modelo de negocios que Hollywood tiene, donde lanzan algo por primera vez en un país, pero muestran trailers a todo el mundo de la nueva película, luego un chico de 14 años de edad en Francia o Alemania no puede verlo por otros seis meses. Si el modelo de negocio fuera uno en donde todos tengan acceso a este contenido al mismo tiempo, no tendrías el problema de la piratería. Así que es realmente, en mi opinión, el gobierno de los Estados Unidos quien protege un modelo anticuado de negocio monopólico que ya no funciona en la era de Internet y eso es a lo que todo se reduce. No soy el rey la piratería, ofrecí un servicio de almacenamiento en línea y ancho de banda a los usuarios, eso es todo.

    Kim Dotcom: Cuando creas algo que es popular, cuando creas una solución, eres un innovador y resuelves problemas para la gente y a ellos les gusta lo que tienes para ofrecer, por supuesto que automáticamente haces dinero. Si tienes un producto que es popular, haces dinero. Yo tenía ese producto que era muy popular.

    John Campbell: ¿Por qué era popular?

    Kim Dotcom: Porque la gente podía sobrepasar muchas limitaciones. Le ahorró mucho dinero a la gente, ya sabes, no necesitabas comprar un servido para almacenar tus archivos, podías utilizarnos para distribuir tus archivos. Archivos legales, tú sabes. Podías usarnos para hacer un respaldo en línea de todos tus archivos. Hay muchos e incontables usos legítimos para Megaupload, que el elemento de la piratería es solamente uno diminuto y no debería ser la principal preocupación.

    John Campbell: En un artículo de CNET que lucía muy bien investigado y fundamentado para mí, decía y cito “entre los dueños de copyright que han acusado a Megaupload de piratería, incluyendo compañías de software y videojuegos, ninguna de ellas presentó al FBI con más, cito, evidencia significativa, fin de la cita, sobre Megaupload que la MPAA. ¿Alguno de los miembros de la MPAA vinieron a decirte “tenemos preocupaciones, Kim, sobre lo que está sucediendo con Megaupload”

    Kim Dotcom: Nunca, y tengo que decirte esto – si tienes una compañía que está siendo muy lastimada por lo que estamos haciendo, miles de millones de dólares en daños, no te esperas sentado a hacer nada. Llamas a tus abogados y tratas de demandarnos y detenernos de lo que estamos haciendo.

    John Campbell: Así que se trata de ceder y desistir de una forma y otra. ¿Recibiste alguna carta de los miembros de la MPAA diciendo “la última película de James Bond está siendo intercambiada infinitamente a través de Megaupload, debes detenerla?

    Kim Dotcom: Por supuesto que no. No nos llegó ningún documento legal de alguno de estos estudios. La única cosa que tenemos son avisos de retirar el sitio con el acceso a la eliminación directa en nuestro sitio web. Por lo que no sorprende que cuando soy el rey de los piratas y estoy haciendo este daño que ninguno de ellos ha intentado demandarnos, hacerlo por daños, ¿sabes? Si tuvieras un negocio que pierde miles de millones de dólares por mi, no te sentarías a hacer nada. Quiero decir, esta investigación llevaba más de dos años, y la compañía vivió por siete años, la MPAA siempre ha tirado nombres contra nosotros y nos han dicho de todo, pero nunca hicieron algo realmente en serio para, ya sabes, llevarnos a la corte por la simple razón que hay una ley en Estados Unidos que nos protege y que es la Digital Millenium Copyright Act, que protege a los proveedores de servicios en línea de acciones de sus usuarios, y esta es la misma ley que permite a Google y YouTube seguir existiendo.

    ¿Sabías que Viacom demandó a YouTube y YouTube usó en su defensa la protección de la DMCA y ganaron? Y si miras a los archivos del caso YouTube, los correos que fueron enviados internamente son un corderito comparado con lo que estaba sucediendo en YouTube en esos momentos, pero esta gente se fue. Ellos ganaron su demanda y yo estoy sentado en la cárcel, mi casa es atacada, todos mis bienes están congelados sin un juicio, sin una audiencia. Esto es completamente una locura, es lo que es.

    John Campbell: ¿Porqué tú entonces, qué piensas?

    Kim Dotcom: Soy un blanco fácil. Mi extravagancia, mi historia como hacker, ya sabes, no soy americano, estoy viviendo en algún lugar de Nueva Zelanda, alrededor del mundo. Tengo divertidos números de placas, ya ves, soy un blanco fácil. No soy Google. Yo no tengo 50 mil millones de dólares en mi cuenta en estos momentos, y ahorita mismo no tengo ni un centavo en mi cuenta. Todos mis abogados están trabajando actualmente sin un centavo, y siguen al pie del cañón haciendo su trabajo, por que lo que están viendo que sucede aquí les parece injusto, es irrazonable y no es justicia.

    John Campbell: ¿En qué pensabas cuando estuviste en la cárcel por un mes? Mucho tiempo contigo mismo, ¿cierto? ¿Tenías un celular? ¿Tenías posibilidad de compartir tiempo con alguien?

    Kim Dotcom: Sí, tenía un celular para mí y estaba básicamente preocupado por mi familia, ya sabes, eso es en lo que estaba pensando principalmente. Tengo una esposa embarazada de mellizos, y es simplemente imposible que mantenga este alto nivel de ansiedad, ellos apelaron mi libertad bajo fianza – y ni siquiera sé con qué fundamentos. Es simplemente ridículo.

    John Campbell: ¿Estás en riesgo de fuga?

    Kim Dotcom: Definitivamente no.

    John Campbell: ¿Existe algún helicóptero esperando literal o metafóricamente sobre la colina, esperando para venir por ti y llevarte a algún sitio desde donde no puedas ser extraditado?

    Kim Dotcom: ¿Sabes que tienes que pensar en esto un minuto, OK? ¿Porqué me iría después de que todo ha sido congelado, todo me ha sido despojado? La compañía que valía probablemente mil millones de dólares o más ha recibido una sentencia de muerte sin juicio, sabes, ¿qué punto tiene para mí el huir? La única cosa que tiene sentido es pelear por esto y eso es exactamente lo que voy a hacer. Voy a pelear por esto hasta el final, y te lo prometo a ti, y a todos los que están viendo esto, voy a ganar porque no soy un criminal y no he hecho algo ilegal.

    John Campbell: La acusación del FBI, sus cargos, que están en extenso documento lleno de uno de los lenguajes más emotivos que haya visto…

    Kim Dotcom: Es un comunicado de prensa. Una acusación de 72 páginas que está diseñada tan maliciosamente para básicamente obtener un juez y un gran jurado en los Estados Unidos para acordar este tipo de acciones de las que nadie había escuchado. Mira a la opinión de los profesionales en temas legales de quienes hayan visto. No es más que un comunicado de prensa lleno de cosas fuera de contexto, diseñado para hacerme ver tan malo como les sea posible.

    John Campbell: ¿Eres tan malo como es posible, Kim? Eres un hombre tan sucio que ha estado haciendo dinero para sí mismo a costa de los creadores de contenido, que se toman el riesgo de hacer su trabajo, quienes hacen cosas, sólo para que tú le permitas a las personas intercambiar sus obras de forma que tú te vuelvas rico?

    Kim Dotcom: Eso completamente no tiene sentido. Soy un innovador, creo software, creo soluciones, creo un website que es popular y que la gente quiere usar, y ha utilizado para muchos usos legítimos y es completamente bizarro cómo estoy siendo puesto en un pedestal como este y señalado como el pirata del planeta. Es una locura. No hay méritos para esto.

    John Campbell: ¿Piensas que estarías en esta posición si no hubieras andado conduciendo con… por decir, el doctor maligno, manejando tu Mercedes en el Gumball Rally por Europa, comportándote en una actitud de inmortal? ¿En una forma que llama la atención hacia ti, que te distingue de las personas que están a cargo de Google y se visten como me visto yo y no publican videos de ellos en YouTube sobre sus comportamientos lunáticos? ¿Es por eso que eres un blanco fácil, tú crees?

    Kim Dotcom: Bueno, antes que todo déjame ser claro. Esos videos y las cosas que ves en línea no son publicadas ahí por mi. Estos videos tienen 10 o más años y yo soy una persona que ama la diversión, ¿ok? Yo disfruto mi vida, hay un gran niño interior en mí y no veo la razón por la que tenga que vestirme de traje y estancarme. Ya sabes, cuando he hecho mi dinero, y disfrutado mi vida, cumplido mis sueños, no hay nada malo con eso. Y esos videos son de mucho antes que tuviera una esposa, y familia e hijos, ya sabes, mis prioridades han cambiado. Soy un hombre de familia, tu sabes, no estoy haciendo este tipo de cosas – eso era un asunto infantil y era muy divertido cuando sucedió y no me arrepiento, pero ese no soy yo ahora, soy un chico diferente. Yo sólo quiero un futuro seguro para mis hijos y, tú sabes, darle a mi familia un gran hogar y esa es la razón por la que nos mudamos a Nueva Zelanda y estamos realmente sorprendidos por lo que está pasando aquí.

    John Campbell: ¿Es por eso que estás aquí? ¿Viniste a Nueva Zelanda a reinventarte y convertirte en un hombre de familia, o viniste a Nueva Zelanda a esconderte de este tipo de cosas, del FBI? ¿Porqué estás aquí?

    Kim Dotcom: No, estoy aquí por mi familia. Tengo niños pequeños, y sabes que vivíamos en Hong Kong. Hong Kong es una jungla de concreto. No hay pasto fresco, no hay árboles, no hay parrillas, ya sabes, no hay aves volando. Quería darle a mis niños un ambiente de felicidad, y naturaleza y paz y eso es por lo que nos vinimos a Nueva Zelanda. Ya sabes, no tienen armas nucleares, no están en las listas de naciones blanco de países con armas nucleares, es increíble. Nueva Zelanda es un hermoso país, vinimos acá en vacaciones, nos enamoramos del lugar y decidimos mudarnos por nuestros hijos, para darles un gran futuro.

    John Campbell: ¿Cuál es tu futuro ahora, Kim?

    Kim Dotcom: Ya sabes, quiero decir, soy un luchador y voy a pelear por esto. Me siento seguro y voy a ganar, porque al final del día, yo sé, mi familia sabe, y todos a mi alrededor saben que no soy un criminal y no he hecho nada malo. Así que pelearé. Es todo lo que puedo hacer.

    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
  • La mejor aplicación VPN que he utilizado al momento: TunnelBear

    Hace ya unos 2 o 3 años que tenía conocimiento de los nuevos modelos de negocio que permitían escuchar música y ver programas de televisión, películas, etc., de manera totalmente legal, por los cuales tenía una enorme curiosidad por probar. Mi curiosidad por estas iniciativas combinadas con mi alta inconformidad por los contenidos de mi entonces contratada compañía de cable, los malísimos contendidos de televisión pública, y todo por supuesto, ensalsado con malos y excesivos comerciales de malos productos o malos políticos, programas repetidos hasta el hartazgo y el sobre explotado formato del reality show, me llevaron a buscar cobijo en estos servicios, probarlos y toparme con sorpresas muy gratas.

    Algunos de los servicios que he probado y con los cuales me he quedado con una buena experiencia son Hulu, Spotify, Pandora, Netflix entre otros. Sin embargo el primer obstáculo con el que me enfrenté al querer probar estos servicios, fue que la mayoría de ellos estaban limitados a atender solo algunas zonas geográficas, es decir, no estaban disponibles para mi país. Por fortuna, la experiencia ya de algunos años me llevó a implementar una solución rápidamente.

    La solución es conceptualmente simple, lo único que hice fue unirme a una VPN (Virtual Private Network), es decir, en términos llanos uní a mi computadora a una red virtual creada en un país donde el servicio que me interesaba efectivamente sí estaba disponible. Pero no todo fue (o es) fácil, ya que aunque la técnica es esencialmente sencilla, los problemas principales oscilan en:

    • Encontrar una VPN en el lugar indicado y que permita el acceso a ella.
    • Ancho de banda suficiente para un buen rendimiento, tanto en la VPN como nuestra conexión local.

    Otro problema presente para algunas personas es,  para decirlo con honestidad, la falta de conocimiento técnico, ya que no les es fácil aplicar esta solución. Es justamente aquí donde la aplicación TunnelBear puede ser de gran ayuda, y reduce la brecha entre los más y los menos avispados en este tema.

    TunnelBear es uno de los mejores programas VPN que he utilizado, proporciona acceso a una VPN de una manera brillantemente simple, con lo cual el usuario obtiene acceso a sitios y servicios restringidos geográficamente, la aplicación se instala como cualquier otra, con opciones de configuración muy sencillas, lo único que se requiere es dar de alta una cuenta en su servicio, el resto lo hace la aplicación por si misma.

    Una vez instalado TunnelBear y al ejecutarlo se nos presenta una interfaz que permite seleccionar la ubicación que deseamos entre Reino Unido (UK) y Estados Unidos (US),  otra opción para prender y apagar la conexión a la VPN, también muestra una gráfica que monitorea el consumo de ancho de banda que se ha hecho.

    Hasta ahora mi experiencia con TunnelBear ha sido muy buena. La aplicación ofrece opción gratuita limitada, y opción de pago sin límite, la cual me parece que vale la pena, mis streamings se ven bien y sin problema.

    Un punto con la red VPN de TunnelBear que también puede ser importante en algunos escenarios, más allá de su uso para el entretenimiento, es la seguridad adicional que provee. Los datos que entran y salen de nuestra conexión estarán más seguros cuando viajan por esta VPN, lo cual hace de TunnelBear una alternativa con respecto a otras aplicaciones como Tor o Hotspot Shield.

    Si le es posible pruébelo y comparta su experiencia.

    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
  • S.O.P.A.

    ¿Qué es y con qué se come S.O.P.A.?

    Desde que ha comenzado el año (2012) me han preguntado ¿que es la Ley S.O.P.A.? unas 5 veces, pero lo más sorprendente fue cuando mi propia madre (ser casi atecnológico) fue la última en hacerlo, ante tal alcance decidí que vale la pena dedicar esta entrada a explicarla y a describir como le afecta a USTED.

    S.O.P.A. son la singlas en inglés para Stop Online Piracy Act (Detener el Acto de Pirateria en Línea) también conocida como HR3261, en términos simples, no es más que una iniciativa de ley acerca del copyright (o derechos de autor) que se debate actualmente en el congreso de los Estado Unidos, hasta aquí alguien podría pensar: ¿y cuál es el problema? o ¿ por qué me debería preocupar si eso no es en mi país?. La polémica es acerca del COMO pretende trabajar esta ley y lo DUDOSO que luce la supuesta intención de esta ley para proteger la propiedad intelectual de las personas que crean algo (música, libros, películas, y un largo etc.). Pero como diría Jack the Ripper: vámonos por partes.

    Cerrar Webs vía S.O.P.A.

    Esta ley quiere implementar métodos donde cualquier sitio, página, blog, programa o servicio de internet que sea acusado (no se establece claramente quien) de utilizar contenido (también se debate que es esto) protegido bajo leyes de propiedad intelectual pueda ser cerrado inmediatamente (de manera cautelar) sin averiguación previa ni la intervención de ningún juez.

    Este tipo de métodos se parecen mucho a los que implementan paises como China, Siria o Irán, para controlar contenido que le pueda resultar adverso al gobierno pertinente de alguna forma, pero ahora implementados por el “campeón de la democracia” U.S.A.

    Los amigos españoles seguramente ya están familiarizados con este tipo de leyes con su infame “Ley Sinde“, y acá los mexicanos nos salvamos por un pelo (y por ahora) de A.C.T.A.

    ¿A quienes pretende afectar S.O.P.A. en Estados Unidos?

    Básicamente a todo aquel relacionado con el contenido “malévolo”, claramente al propietario o creador de la web, servicio, software o lo que sea que ayude a distribuir el contenido indebido, buscadores,  proveedores de internet (ISPs), hostings etc. Se pretende que S.O.P.A obligue incluso a los ISPs, hostings o servicios/empresas como Facebook , Twitter, Google, YouTube entre muchos otros, a que vigilen y proporcionen información de usuarios que hacen uso de contenido “inapropiado” mientras que censuran a este, servicios de pago como PayPal deberán suspender cuentas y pagos a sitios considerados ilegales. Una de mis favoritas, si usted tiene un blog y un usuario coloca un enlace que sea considerado como ilegal, el blog completo podría hacerse de castigo y ser cerrado por considerarlo a USTED propietario de dicho blog, como cómplice de un acto ilegal. Como decimos en México ¡échece ese trompo a la uña!

    Aquí es donde la bandera de la “defensa de la propiedad intelectual” se pone en duda, ya que de aprobar leyes de esta naturaleza se comienzan a poner en peligro cosas como libertad de expresión, sana competencia, derecho a la privacidad, etc.

    ¿Cómo le afecta a usted y el resto del mundo?

    Antes de que crea que esto sólo afecta y compete a los estadounidenses piense lo siguente. Si bien la ley solo rige el territorio de los Estados Unidos, es en este país donde se concentran la mayor parte de los servicios, compañías e infraestructura con la que trabaja internet y por lo tanto USTED.  Existen muchos otras páginas o servicios que no son de origen estadounidense, que sin embargo, se encuentran alojados en servidores que se encuetran físicamente en territorio de los Estados Unidos, por lo que estarían también bajo la jurisdicción de la ley.

    Otros efectos

    El mundo siempre está viviendo cambios, y algunos de ellos para bien y para mal son gracias a diversos movimientos sociales que se ven reflejados en el arte, la protesta, la propuesta, la creación de nuevas alternativas tecnológicas o políticas que van muchas veces en contra o en otro sentido de lo hoy establecido, y que por lo tanto rozan en muchísimas ocasiones lo que se considera en este momento legal, aceptable, apropiado o de buen gusto. Por todo esto muchas personas o movimientos con intenciones legítimas correrían el riesgo de ser criminalizados de aprobarse leyes de este tipo.

    ¿Quiénes promuven S.O.P.A.?

    Esta ley S.O.P.A. fue introducida por Lamar Smith por el partido republicano pero ha sido a compañado por otros varios legisladores y respaldado por una buena cantidad de compañías, no quiero entrar en tanto detalle pero aquí un par de enlaces para ver quienes apoyan a esta ley (sujetas a cambio sin previo aviso):

    Compañías

    Legisladores

    Conclusión

    Es correcto hacer leyes que nos protejan a todos en diversos escenarios, lo que no está bien es que en la búsqueda de la protección a un solo aspecto se deterioren otros frentes, y que esto cause al final que una supuesta solución tenga un costo más alto que el del problema que se debía solucionar en primer lugar, y mucho menos si todo es un pretexto para privilegiar a algunos y solapar su falta de competitividad, creatividad o simple ineptitud.

    Algunos enlaces de interés:

    S.O.P.A. (Wikipedia)

    A.C.T.A. (Wikipedia)

    The Internet American Moratorium Act (IAMA)

    The Privatization of Copyright Lawmaking

    No Comment
  • Mitos y Realidades del HTML5 (Presentación)

    Durante mis últimas visitas a algunas instituciones de educación superior he utilizado como material de apoyo durante las charla sobre HTML5 una presentación que elaboré basado en la idea original de Marcin Wichary.

    He de aclarar que  la versión original está muy bien y el código está disponible de forma  libre, pero no utilicé nada del código de Wichary debido  a que es un poco extenso y un tanto desordenado (me parece),  por lo que hice mi propia implementación pero manteniendo el mismo concepto visual, de manera que mi versión no sirve para entender la versión de Wichary así que sugiero que los vea como ejemplos distintos si desea meterse al código.

    Una vez aclarado lo anterior, la presentación muestra una serie láminas o slides que hablan de los mitos y realidades que rodean a HTML5, cada lámina tiene un comentario que le da contexto, para ver los comentarios hay que presionar la tecla 2 y para navegar entre slides simplemente hay que usar las teclas direccionales.

    El contenido de esta presentación fué creada con la idea de servir como introducción al HTML5 utilizando al mismo HTML5 como medio, es decir,  es una presentación creada usando HTML5 para enseñar HTML5 (interesante ¿no?), de manera que puede servir como presentación de introducción al HTML5 o como ejemplo de código HTML5 implementado para una pequeña aplicación multimedia.

    Pongo a su disposición esta ejemplo para que haga con el ¡lo que quiera!, modifíquelo, bórrelo, descompóngalo, recompóngolo, increméntelo, decreméntalo…en fin, lo que usted quiera, si desea darme crédito se lo agredeceré y si no, no importa porque seguramente nunca me enteraré  :)))

    No he comentado bien el código (¡sorry!) y normalmente casi todo los nombres de variables y funciones los hago en inglés, espero que esto no le represente mayor problema,  en realidad la lógica es sencilla (si se le complica siempre puede enviarme un mensaje y trataré de ayudarle con algún tip), pero no se desanime, si tiene bases de programación y le dedica un poco de tiempo estará manejando y modificando el código antes de lo que cree.

    Debo aclarar también que este código fué creado para Google Chrome por lo que podría no verse adecuadamente en otros navegadores, sin más le dejo el enlace para descargar el código:  HTML5MitosRealidades.rar

    2 Comments
  • De HTML5 en el Tecnológico de Estudios Superiores de Jocotitlán

    Para terminar el año con gusto el día 8 de diciembre tuve la oportunidad de que en esta ocasión me invitaran a platicar con los estudiantes y profesores del Tecnológico de Estudios Superiores de Jocotitlán en el marco del primer Congreso Mexiquense CTS+I  acerca de HTML5.

    Durante un poco más de una hora los asistentes a esta conferencia y yo estuvimos hablando acerca de las novedades que nos ofrece esta tecnología mientras aclarábamos algunos puntos respecto al tema. En todo momento tuve una gran y divertida participación de los presentes, lo cual agradezco esperando que se la hayan pasado tan bien como yo.

    Debo decir que desde que llegue al campus del tecnológico recibí un trato excepcional por parte del comité organizador del evento formado por estudiantes y profesores. También pude colarme por un rato a un par de interesantes conferencias que desafortunadamente no pude terminar de escuchar pero disfruté mucho mientras estuve presente.

    También tengo que admitir que quedé en deuda con uno de los chicos que ayudaban en la organización del evento porque los representantes de mi editorial y yo quedamos de obsequiarle un libro pero ya no lo encontramos cuando quisimos entregárselo.

    En fin, no me queda más que felicitar y agradecer a los organizadores del evento, a todas las personas que me hicieron el favor de acompañarme durante la conferencia y en general al Tecnológico de Estudios Superiores de Jocotitlán y por supuesto a AlfaOmega Grupo Editorial, a todos ustedes, gracias.

    No Comment
  • HTML vs XHTML

    Diferencia entre HTML y XHTML

    Antecedentes

    Nosotros como Mafalda debemos ser curiosos  (Esperemos que el Sr. Quino por favor no me demande, !es por una buena causa!.)

    Esta es una de las preguntas más comunes a las que todo desarrollador web llega en sus inicios ¿cuál es la diferencia entre HTML y XHTML?, para aquellos con suficiente experiencia, la respuesta es sencilla y puede parecer obvia, pero la verdad es que para las personas que comienzan a sumergirse dentro del desarrollo web, es de hecho una muy buena pregunta ,que se ha de contestar en esta ocasión :).

    A finales de 1994 Berners-Lee fundó el World Wide Web Consortium (W3C), para desarrollar y distribuir estándares para las tecnologías web, comenzando con HTML. Las primeras versiones de HTML fueron aprobadas a lo largo de la década de los 90s.  En 1999 se aprobó la versión HTML 4.01 y más tarde en 2001 se creo su redefinición utilizando XML conocido como estádar XHTML1.0 para finalmente ser aprobado y recomendado por la W3C en Mayo de ese mismo año y conocido como el estándar XHTML1.1.

    Con peras y manzanas por favor…

    Un archivo HTML es básicamente un archivo de texto común y corriente, en el se colocan una serie de etiquetas (o tags) que tienen sentido para un servidor web y para los navegadores que interpretan su contenido para finalmente mostrarlo al usuario. Sin embargo, las reglas que utiliza un navegador para interpretar un archivo HTML no son precisamente estrictas, por lo que a veces al creador de un documento HTML se le “perdonan” algunas imprecisiones e incluso errores. Esto puede parecer una ventaja, pero en muchos casos el programador de páginas debería de darse cuenta de algunos de estos errores que pueden quedar desapercibidos gracias a la permisibilidad otorgada por HTML, o simplemente se pueden generar malos hábitos de programación junto con algunas ideas erróneas.

    Los beneficios de XHTML

    Es para corregir esta situación que se crea XHTML acrónimo en inglés de eXtensible Hypertext Markup Language, que inicialmente comenzó a tratar a HTML simplemente como un documento XML, y como tal debe cumplir reglas más estrictas en cuanto a la escritura de tags o etiquetas, es decir, se debe ser sintáctimente correcto (todo en minúsculas, elementos correctamente cerrados, etc.), como por ejemplo, una etiqueta de quiebre de línea: si escribimos <br> en el esquema permisivo de HTML no habrá  ningún problema, pero si de la misma manera se coloca dentro del formato XHTML ese código será incorrecto, por lo que se debe escribe <br />, es decir, se debe cerrar el elemento como sucede en un archivo XML.

    Esencialmente XHTML busca que los programadores creen documentos sintácticamente correctos y con esto lograr código más limpio, correcto, consistente de mejor legibilidad. Para que todo tenga sentido, adicionalmente se debe especificar el tipo MIME de documentos creados como XHTMLs, mientras que para un documento HTML el tipo MIME es text/html para un XHTML es application/xhtml+xml.

    Adicionalmente durante la evolución de XHTML se integró la validación contra un DTD, que no es más que otro documento XML que  colecciona los elementos (etiquetas) válidos en un XHTML, si algo no está bien escrito editores modernos pueden señalar el error para que el programador se dé cuenta e haga las correcciones necesarias.

    A usar todos XHTML….o no

    Hasta aquí cualquiera podría pensar: OK entonces hagamos todo en XHTML, pero durante la existencia de XHTML este siempre tuvo el problema de que varios servidores web no generaban el código escrito con el tipo MIME application/xhtml+xml  sino simplemente como text/html , o peor aun, los programadores de páginas web a pesar de respetar las reglas sintácticas de XHTML simplemente no señalaban el tipo application/xhtml+xml, lo cual causa que los documentos sigan siendo tratados con el tipo text/html. Sumado a esto, la validación con el DTD no garantiza que la página en cuestión sea corregida ya que a pesar de señalar algún error, si el programador no lo soluciona la mayoría de los navegadores simplemente interpretarán ese código permisivamente, justo como pasa con el HTML común.

    Debido a lo anterior XHTML realmente nunca funcionó como un real sustituto de HTML (que era lo que se buscaba), la W3C intentó seguir evolucionando XHTML con una versión 2 pero con la llegada de la especificación HTML5 desistió de ello, incluyendo en HTML5 muchas de los requerimiento sintácticos de XHTML.

    El futuro de XHTML

    Los que ya están en el camino de HTML5 podrán decir:  ¿pero que hay de XHTML5?, efectivamente existe XHTML5, pero este NO es exactamente una evolución del XHTML antiguo (no hubo versión 2, 3 ni 4 de XHTML), pero sí hay relación en el sentido de que XHTML5 trata al código HTML5 como un XML y lo valida como tal por lo que hay que cumplir con lo que exige un XML. Pero el real objetivo apunta a otro lado, las W3C ha hecho mucho énfasis en la semántica de HTML5 lo cuál se fortalece al serializar un archivo HTML5 como un XML, esto significa que si un archivo está serializado, facilita a aplicaciones externas (motores de búsqueda, programas de accesibilidad, etc.) la interpretación modular (o por partes) de los documentos que creamos.

    Lo anterior quizá se oye más complejo de lo que es en realidad es, pero piense lo siguiente, digamos que usted requiere crear un programa que analice solo una parte del contenido de una página web. Si analiza el código de esa página web como texto plano usted requiere hacer mucho código de manejo de cadenas para extraer la parte que le interesa. En cambio, si el documentos viene serializado como un XML usted puede hacer uso de recursos como Xpath (por ejemplo) para extraer la parte  que le interesa con mucha más facilidad. De esta forma usted puede facilitar la explotación del contenido de una página para usted o para terceros.

    Creo que por el momento esto es lo que hay en el pasado y en el horizonte de XHTML y HTML en términos generales, pero ahora que conoce la diferencia entre ambos la decisión de cual usar es totalmente suya, sin embargo recuerde que HTML5 (y XHTML5) a la fecha se sigue desarrollando y el soporte por parte de los navegadores también, de manera que siempre debemos estar atentos a cualquier cambio.

    Enlaces que pueden interesarle:

    Arrancar con HTML5 Curso de Programación (Libro gratis)

    HTML (Mozilla group)

    HTML and XHTML

    Libros que pueden ser de su interés:

    No Comment