sábado, 8 de diciembre de 2012

Sincronizar Scroll de contenedores DIV

Cuando estamos desarrollando páginas Web en ciertos casos necesitamos usar un mismo scroll para diferentes contenedores.

Un ejemplo sería el tener una tabla de gran tamaño (tal y como se muestra en el siguiente ejemplo) y que necesitemos que la cabecera nunca se oculta al desplazarnos con el scroll.

Columna 1 Columna 2 Columna 3 Columna 4 Columna 5
Dato 1.1 Dato 2.1 Dato 3.1 Dato 4.1 Dato 5.1
Dato 1.2 Dato 2.2 Dato 3.2 Dato 4.2 Dato 5.2
Dato 1.3 Dato 2.3 Dato 3.3 Dato 4.3 Dato 5.3
Dato 1.4 Dato 2.4 Dato 3.4 Dato 4.4 Dato 5.4
Dato 1.5 Dato 2.5 Dato 3.5 Dato 4.5 Dato 5.5
Dato 1.6 Dato 2.6 Dato 3.6 Dato 4.6 Dato 5.6
Dato 1.7 Dato 2.7 Dato 3.7 Dato 4.7 Dato 5.7

En la tabla de ejemplo si nos desplazamos con el scroll vertical, se perderán las cabeceras de la tabla. Una solución para ello es colocar la cabecera en un div diferente, como se ve a continuación.

Columna 1 Columna 2 Columna 3 Columna 4 Columna 5
Dato 1.1 Dato 2.1 Dato 3.1 Dato 4.1 Dato 5.1
Dato 1.2 Dato 2.2 Dato 3.2 Dato 4.2 Dato 5.2
Dato 1.3 Dato 2.3 Dato 3.3 Dato 4.3 Dato 5.3
Dato 1.4 Dato 2.4 Dato 3.4 Dato 4.4 Dato 5.4
Dato 1.5 Dato 2.5 Dato 3.5 Dato 4.5 Dato 5.5
Dato 1.6 Dato 2.6 Dato 3.6 Dato 4.6 Dato 5.6
Dato 1.7 Dato 2.7 Dato 3.7 Dato 4.7 Dato 5.7

Ahora no se perderán las cabeceras, sin embargo, si usamos el scroll horizontal, las cabeceras no coincidiran con las columnas. Para solucionar esto vamos a sincronizar mediante javascript el scroll en ambos contenedores. Veamos el código correspondiente.


<div id="cabeceraTabla" style="border: 1px solid; overflow: hidden; width: 600px;">
<table>
 <!-- Aquí la cabecera de la tabla -->
</table>
</div>
<div  id="valoresTabla" style="border: 1px solid; height: 100px; overflow: auto; width: 600px;">
<table>
  <!-- Aquí los datos de la tabla -->
</table>
</div>

 <script>

                    document.getElementById("valoresTabla").onscroll = function ()
                    {
                        try
                        {
                            document.getElementById('cabeceraTabla').scrollLeft = document.getElementById('
valoresTabla').scrollLeft;
                        }
                        catch (ex){alert(ex);}
                    };

</script>


Se trata de asignar un nombre a cada uno de los contenedores (cabeceraTabla y valoresTabla), posteriormente lo que se está haciendo es asignar una función al evento de scroll, de modo que al modificar la posición del scroll se asigna esa misma posición al scroll de la cabecera.

Se puede hacer lo mismo con el scroll vertical en caso de que queramos que la primera columna no se oculte. En tal caso la propiedad del objeto que se modifica es scrollTop.

Columna 1 Columna 2 Columna 3 Columna 4 Columna 5
Dato 1.1 Dato 2.1 Dato 3.1 Dato 4.1 Dato 5.1
Dato 1.2 Dato 2.2 Dato 3.2 Dato 4.2 Dato 5.2
Dato 1.3 Dato 2.3 Dato 3.3 Dato 4.3 Dato 5.3
Dato 1.4 Dato 2.4 Dato 3.4 Dato 4.4 Dato 5.4
Dato 1.5 Dato 2.5 Dato 3.5 Dato 4.5 Dato 5.5
Dato 1.6 Dato 2.6 Dato 3.6 Dato 4.6 Dato 5.6
Dato 1.7 Dato 2.7 Dato 3.7 Dato 4.7 Dato 5.7



viernes, 27 de julio de 2012

Primeros pasos con Ajax

AJAX ( Asynchronous JavaScript And XML). Se trata de una tecnología orientada a la creación de aplicaciones Web interactivas. La idea es que la aplicación se comunique con el servidor sin necesidad de recargar la página entera.

Vamos a ver un ejemplo sencillo que consiste en cargar el contenido de un archivo de texto que se encuentra en el servidor y lo muestra en pantalla.

Lo primero que debemos hacer es crear un archivo html en el cual incluiremos el siguiente código


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Mi primer AJAX</title>

<script type="text/javascript">
var peticion;
// Función que carga el archivo
function loadText()
{   
  try
  {
    if (peticion.readyState == 4)
    {       
      if (peticion.status == 200)
      {       
        // Mostrar el contenido       
        document.getElementById('contenido').innerHTML = document.getElementById('contenido').innerHTML + '<br/>' + peticion.responseText;       
      }
    }
  }
  catch (err)
  {
    alert(err);
  }
}

function cargar()
{
  try
  {
    // Obtener la instancia del objeto XMLHttpRequest
    peticion = new XMLHttpRequest();
    // Preparar la funcion de respuesta. Con indicamos que funcción ejecutar
    // cuando el servidor retorne la respuesta
    peticion.onreadystatechange = loadText;

    // Preparar la petición
    peticion.open('GET', 'http://localhost/ajax/ajax.txt', true);
    // Enviar la petición al servidor
    peticion.send(null);
  }
  catch (err)
  {
    alert(err);
  }
}

</script>

</head>
<body>
    <input type="button" value="Cargar Archivo" onclick="javascript:cargar();"/>
    <div id="contenido" style="cursor:pointer" onclick=""></div>
</body>
</html>



Vamos a analizar un poco el código. En nuestra página web tendremos un botón y un contenedor div. Cuando se pulsa sobre el botón se ejecuta la función cargar y es en esta función donde vamos a usar AJAX.

Lo primero que se hace en la función cargar es obtener objeto que implementa la interfase XMLHttpRequest. XMLHttpRequest es una interfase utilizada para realizar peticiones HTTP y HTTPS a servidores Web.



  peticion = new XMLHttpRequest();


Posteriormente enlazamos la asignamos la función loadText a la propiedad onreadystatechange. Esto hace que cada vez que el atributo readyState del objeto petición cambie. En la función loadText se verifica que el estado tenga el valor 4, en este momento el servidor a respondido y la respuesta está disponible. Por otro lado se verifica que la respuesta es correcta para esto se verifica el atributo status si el valor es 200 entonces la petición se ha devuelto correctamente.


  peticion.onreadystatechange = loadText;



Finalmente se prepara la conexión y se envía la misma. Para preparar la conexión se usa la función open que tiene res parámetros:
  • String que indica el tipo de petición. Esta puede tener los valores GET, POST o HEAD. En el caso del ejemplo la url donde he puesto el recurso es http://localhost:/ajax/ajax.txt.
  • La url del recurso.
  • Un tercer parámetro opcional que indica si la petición será síncrona o asíncrona. Sólo usaremos este parámetro con el valor a falso si no necesitamos esperar por la respuesta.
Una vez preparada la conexión se ejecuta la función send que se encarga de mandar la petición al servidor. Esta función tiene como parámetro un string que se usará para el paso de parámetros a las peticiones de tipo POST.




    // Preparar la petición
    peticion.open('GET', 'http://localhost:/ajax/ajax.txt', true);
    // Enviar la petición al servidor
    peticion.send(null);


Finalmente se añade al contenido al div

  
        // Mostrar el contenido       
        document.getElementById('contenido').innerHTML = document.getElementById('contenido').innerHTML + '<br/>' + 

        peticion.responseText;       


lunes, 23 de julio de 2012

Usar plantillas en JSF

Usar plantillas en JSF.

Cuando realizamos un proyecto web es normal que tengamos una base que se repita en todas nuestras páginas como podría ser un menú, mensajes de error o cualquier otro elemento que se nos ocurra. No tendría mucho sentido repetir este código en todas las páginas pues si por ejemplo decidiéramos cambiar una opción del menú, tendríamos que ir página a página y cambiar el código. Es por ello que se usan plantillas que definen los elementos comunes a usar.

En este artículo vamos a ver como usar plantillas en JSF.



Como primer paso vamos a crear un proyecto JSF, tal y como expliqué en el artículo de primeros pasos con JSF.

Una vez que tengamos el proyecto creado crearemos una carpeta con el nombre plantilla donde vamos a guardar las plantillas que creemos.

Ahora se debe crear un documento xhtml. En nuestro ejemplo lo llamaremos platilla_principal.xhtml. Como ejemplo añadiremos un pequeño menú en la parte superior. El archivo platilla_principal.xhtml contendrá el siguiente código:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets">
    <head>
        <ui:insert name="contentido_cabecera"></ui:insert>
    </head>
    <body>
        <div id="menu">
            <ui:include src="menu.xhtml"></ui:include>
        </div>       
        <div id="contenido">
            <ui:insert name="contentido_pagina"></ui:insert>
        </div>
    </body>
</html>



Hay dos etiquetas que se han usado en la creación de la página anterior:
  • ui:include. Esta etiqueta permite introducir el contenido de un archivo en la posición donde se encuentre.
  • ui:insert. Permite definir bloques que posteriormente serán sustituidos por el código que indiquemos en nuestras páginas tal y como veremos posteriormente.
Ahora crearemos el archivo menu.xhtml que hemos incluido en la platilla a través de la etiqueta ui:include.



<ui:composition xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:c="http://java.sun.com/jstl/core">
  
<style type="text/css">
  boton
  {
    width: 80px;
    height: 20px;
    float:left;
    background-color: cyan;
    text-align: center;
    margin:10px;
    font-size:12px;
    padding-top:5px;
    cursor:pointer;
    font-weight: bold;
    color: white;       
    background-image: -moz-linear-gradient(100% 100% 180deg, #2F2727, #1a82f7) !important; /* Firefox */
    background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#1a82f7), to(#2F2727)) !important;  /* Webkit: Chrome, Opera,... */   
    background-color: #1a82f7; /* Navegadores sin CSS3 */
    background-&amp;amp;amp;#8203;&amp;amp;amp;#8203;image: linear-gradient(left , #1a82f7, #2F2727 ); /* CSS3 puro */   
  }
</style>
  <div style="float:left; width: 100%;">
    <div class="boton"> Menu 1 </div>
    <div class="boton"> Menu 2 </div>
    <div class="boton"> Menu 3 </div>
  </div>
</ui:composition> 

Finalmente debemos modificar nuestras páginas index.xhtml y testJSF.xhtml.


<ui:composition xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:c="http://java.sun.com/jstl/core"
  template="plantillas/plantilla_principal.xhtml">   
   
   
    <ui:define name="contentido_cabecera">
        <title>Mi primer proyecto JSF 2.0 con plantillas</title>
    </ui:define>
   
    <ui:define name="contentido_pagina">
        <h:form>
            <h:inputText value="#{testBean.descripcion}"></h:inputText>
            <h:commandButton value="Enviar Formulario" action="testJSF"></h:commandButton>
        </h:form>
    </ui:define>
   
</ui:composition>




<ui:composition xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:c="http://java.sun.com/jstl/core"
  template="plantillas/plantilla_principal.xhtml">   
   
   
    <ui:define name="contentido_cabecera">
        <title>Mi primer proyecto JSF 2.0</title>
    </ui:define>
   
    <ui:define name="contentido_pagina">
        <!-- Creamos un formulario -->
        Tu texto: #{testBean.descripcion}
    </ui:define>
   
</ui:composition>


Vemos que se han usado nuevas etiquetas:
  • ui:composition. Para definir un bloque e indicar  que plantilla se va a usar.
  • ui:define. Esta etiqueta queda asociada a la etiqueta ui:insert vista con anterioridad. Lo que hacemos con ella es decirle a JSF que el contenido dentro de esta etiqueta debe incorporarse en la plantilla en la posición indicada por ui:insert que tenga el mismo nombre.
Ahora sólo será necesario que despleguemos la aplicación y la probemos.

domingo, 22 de julio de 2012

Prineros Pasos con JSF2

¿Qué es JSF?

Cuando veáis en algún sitio las siglas JSF estás significan JavaServer Faces. Se trata de un framework para el desarrollo de aplicaciones web basadas en Java. Su funcionalidad se encuentra orientada a la realización de las interfaces gráficas simplificando notablemente el desarrollo de las mismas.

¿Qué necesito para empezar?

Para empezar a trabajar necesitaras: tener instalado java, un entorno de desarrollo para Java como podría ser Eclipse o Netbeans, un servidor de aplicaciones como podrían ser JBoss o GlassFish y las librerías para JSF 2.

Una manera simple de obtener todo lo necesario es descargar la última versión Java EE de Netbeans la cual incluye todo lo que vas a necesitar. Puedes realizar la descarga de manera totalmente gratuita desde aquí.

Instalando Netbeans.

Una vez descargado instalamos ejecutamos el archivo y comenzará la instalación.


Como vemos en la imagen se nos pregunta que servidor de aplicaciones instalar, en este caso sólo será necesario que nos instalemos el servidor GlassFish.

Una vez instalado ya es posible comenzar a desarrollar nuestro proyecto.

Creando el proyecto.

Arrancamos la aplicación NetBeans y creamos un nuevo proyecto para ello vamos a la opción de menú File y seleccionamos New Project. Nos aparecerá la siguiente pantalla:



donde seleccionaremos como categoría Java Web y como proyecto Web Application. En las siguientes pantallas que aparecen seleccionaremos el nombre del proyecto, su ubicación y el servidor en el cual se va a ejecutar el proyecto, en nuestro caso será el servidor GlassFish.



La siguiente pantalla que nos aparece en el asistente es la que nos va a permitir incluir las librerías JSF necesarias.
Marcaremos en la lista de frameworks a usar JavaServer Faces. En la parte inferior nos aparecerán a configuración del framework debemos asegurarnos de que en Server Library aparezca JSF 2.0. Una vez hecho esto ya podemos pulsar sobre finalizar tendremos creado la base del proyecto, incluyendo todas las librerías y configuraciones básicas necesarias.

 

 Modificando el proyecto base.


Inicialmente nos aparecerá una página index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        Hello from Facelets
    </h:body>
</html>


y un archivo de configuración web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>
</web-app>


Lo primeros que vamos a hacer es crear un JavaBean. Para aquellos que no sepan lo que es decir que se trata de un modelo de componentes usados para la encapsulación de varios objetos en un sólo objeto. De una manera simple podemos digamos que es una clase la cual tendrá una sería de atributos existiendo para cada uno de ellos una función de recuperación con el nombre getNombre_atributo  y una función de actualización con el nombre setNombre_atributo

Nuestro bean de ejemplo tendrá como atributo un String llamado descripcion, tal y como vemos a continuación.

package com.losada.jsf.bean;

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

/**
 *
 * @author luis
 */
@ManagedBean(name="testBean")
@SessionScoped
public class TestJSF implements Serializable {

    private String descripcion;

    public String getDescripcion() {
        return descripcion;
    }

    public void setDescripcion(String descripcion) {
        this.descripcion = descripcion;
    }
}



Puede verse que se han añadido al bean dos etiquetas:
  • @ManagedBean(name="testBean"). Esta etiqueta indica a la aplicación que se trata de un bean que será usado para comunicarse con las páginas web que creemos mediante las etiquetas JSF.
  • @SessionScooped. Indica que la información se mantendrá durante toda la sesión de modo que mientras está se encuentre abierta los valores de los atributos del bean se mantendrán.
 Como siguiente paso vamos a modificar index.xhtml. Como vemos se añaden varias etiquetas:
  • h:form. Esta generará posteriormente el código html para un formulario.
  • h:inputText. Esta etiqueta generará un campo de entrada de datos que estará asociado al atributo descripción de nuestro bean.
  • h:commandButton. Generará un botón, al pulsarlo se hará un setDescripcion sobre nuestro bean y tras esto se cargará la página indicada en la propiedad action (en nuestro caso testJSF).

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Mi primer proyecto JSF 2.0</title>
    </h:head>
    <h:body>       
        <!-- Creamos un formulario -->
        <h:form>
            <h:inputText value="#{testBean.descripcion}"></h:inputText>
            <h:commandButton value="Enviar Formulario" action="testJSF"></h:commandButton>
        </h:form>
    </h:body>
</html>




Finalmente creamos un nuevo archivo testJSF.xhtml. Tal y como se muestra a continuación.


<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Mi primer proyecto JSF 2.0</title>
    </h:head>
    <h:body>       
        <!-- Creamos un formulario -->
        Tu texto: #{testBean.descripcion}
    </h:body>
</html>


Con esto ya tenemos nuestro proyecto finalizado. Para probarlo ir al menú contextual que aparece sobre nuestro proyecto y seleccionamos Deploy. Esto arrancará el servidor de aplicaciones si este no se encuentra arrancado ya y realizará el despliegue de la aplicación en el mismo.

Finalmente abriremos un navegador y cargaremos la misma:


 Como vemos nos aparece un formulario en el cual podemos introducir un texto y una vez que pulsemos sobre el botón se enviará el formulario.


Así hemos creado nuestra primera aplicación JSF 2.0. Este es un ejemplo muy sencillo pero es posible complicarlo mucha mas realizando aplicaciones complejas.

Por ejemplo en el atributo action del botón es posible no poner directamente una página de destino sino decirle que ejecute una función dentro del bean y en función del resultado de la misma ir a distintas páginas que tengamos definidas.

Por otro lado existen frameworks de componentes visuales como es el caso de richfaces (que veremos mas adelante en otro artículo). De modo que tendremos componentes mucho más complejos que nos facilitarán el trabajo de manera notable.