- EL CONOCIMIENTO ES Y DEBE SER LIBRE -

viernes, julio 23, 2010

Conociendo la Grilla de SmartGWT (PARTE I)

Uno de los motivos por la que use este framework fue su Grilla (ListGrid y TreeGrid) su potencia lo pueden ver en el showcase pero hay una característica que no se muestra muy claro en el showcase de ejemplos (debido a que los ejemplos corren solo en el lado del cliente) que es lo que se denomina: “live grid”. El término “live grid” hace referencia a la capacidad que tiene la grilla de capturar datos del servidor conforme deslizamos la barra de desplazamiento.

En el ejemplo que muestro a continuación la Grilla (listgrid) captura 15 registros cada vez que deslizamos la barra de desplazamiento. El total de registros a capturar será de 5000, debes de notar que puedes desplazarte a los últimos registros sin necesidad de mostrar todos los anteriores (te sugiero que veas el video al final del post para mayor entendimiento)

ListGrid solicita los primeros 15 registros al Servidor mediante las variables “startRow” y “endRow” con los valores 0 y 15 respectivamente (la asignación de estas variables se realizan automáticamente y sirven para controlar el envió de registros del lado del Servidor), una vez recibidos los registros solicitados por ListGrid este procede a solicitar los siguiente 15 registros modificando las variables “startRow=15” y “endRow=30” y así sucesivamente, esto se ve claramente en el video-guía.

Ahora explicaremos algo del código fuente: “Blogspot.java”, en la línea  27 se le dice a la Grilla que capture 15 registros por requerimiento, además en la línea 29 le decimos a la grilla que  auto capture la data conforme deslizamos la barra de desplazamiento.
/*
*Codigo Fuente Blogspot.java
*/
public class Blogspot implements EntryPoint {
 
 public void onModuleLoad() {
  
 DataSourceIntegerField id = new DataSourceIntegerField("id","id",20);
    id.setPrimaryKey(true); 
    DataSourceTextField descripcion = new DataSourceTextField("descripcion");
   
    //preparamos para la captura de la data
    OperationBinding fetch = new OperationBinding();
    fetch.setOperationType(DSOperationType.FETCH);
    fetch.setDataProtocol(DSProtocol.POSTPARAMS);
    
    RestDataSource data=new RestDataSource();  
    data.setOperationBindings(fetch);
    data.setDataFormat(DSDataFormat.JSON);
    data.setFetchDataURL("fetch.php");
    data.setFields(id,descripcion);
    
        ListGrid lg=new ListGrid();
     lg.setCanFreezeFields(true);
     lg.setHeight(200);
     //capturamos 15 registros por pagina
     lg.setDataPageSize(15);
   
     lg.setAutoFetchData(true);
     lg.setDataSource(data);
     lg.setShowAllRecords(false);
     
     RootPanel.get("idImgVertical").add(lg);
 }
}
/*
* Codigo fuente de fetch.php
*/
$st=$_POST["_startRow"];
$en=$_POST["_endRow"];

$data=array();

for($i=0;$i<15;$i++)
{
 $data[$i]['id']=$st+$i;
 $data[$i]['descripcion']='descricion de :'.$i; 
}
$mensaje=array();
$mensaje['response']['status']=0;
$mensaje['response']['startRow']=$st;
$mensaje['response']['endRow']=$en;
$mensaje['response']['totalRows']=5000;
$mensaje['response']['data']=$data;

echo json_encode($mensaje);

lunes, julio 12, 2010

Integrando jQuery, Gwt y Php

La idea de este Post no es realizar un  tutorial, sino una guía de introducción que permitan al programador de una manera rápida ver de qué trata el asunto. Al final se muestra un pequeño ejemplo junto con su respectivo video-guía de implementación para que cualquiera con algo de entusiasmo pueda realizarlo.

La integración  de jQuery a GWT se consigue a través de JSNI(JavaScript Native Interfaze) y la integración de GWT con PHP lo realizaremos a través de RestDataSource (librería de SmartGWT).
Lectura Obligada: GWT Style, Configuration and JSNI Reference

Introducción
El JSNI nos brinda la posibilidad de utilizar métodos Java que contengan código JavaScript, estos métodos de Java deberán de tener el modificador  “native”, con este modificador le comunicamos al compilador que no valide su contenido.

Llamado métodos JavaScript de Java
Llamar métodos JavaScript de Java es bastante sencillo, solo tienes que tener en cuenta los alias de los objetos JavaScript:  “window” y “document”,  que son:  “$wnd” y “$doc” respectivamente.
//Capturamos la imagen snapshot del video
 public native String getImageUrl(String cad)/*-{ 
  //aca llamamos a JavaScript de Java
  return $wnd.$.jYoutube(cad);  
 }-*/;


Llamando métodos Java de JavaScript
Llamar métodos Java de JavaScript implica el manejo de una sintaxis especial.
[instance-expr.]@class-name::method-name(param-signature)(arguments)
La explicación de esta sintaxis la encuentran  acá. (Para encontrar el “class-name” use el autocompletado  de Eclipse, y no se hagan tanto rollo con eso de “fully qualified name”).
//Mostramos la imagen sin efecto 
 public void ShowImage(String url)
 {
  ImgPrincipal.setUrl(url);
 }
  
   //Ocultamos la imagen con efecto SLOW 
 public native void HideImage(String url)/*-{ 
  var tempThis=this;  
  $wnd.$("#idImgPrincipal").hide('slow',function(){          
    //aca llamamos a Java de JavaScript
    tempThis.@jsni.pck.client.Jsni::ShowImage(Ljava/lang/String;)(url);
    $wnd.$("#idImgPrincipal").show('fast');
  });    
 }-*/;
No está de más mencionar que “ShowImage” y “HideImage” pueden ser llamados desde cualquier parte de nuestra aplicación Java.


Pasando valores entre Java y JavaScript y viceversa
Este tema no es complicado, pero en el documento del inicio del Post hay una muy buena guía sobre este tema.

Integración con PHP
Se puede utilizar la integración con php a través de RequestBuilder, pero nosotros utilizaremos RestDataSource que como verán en el ejemplo nos brinda la data ya formateada, de modo tal que su utilización se hace mucho más fácil; ya que, no tenemos que lidear con el formato JSON directamente.
//preparamos para la captura de la data
  OperationBinding fetch = new OperationBinding();
  fetch.setOperationType(DSOperationType.FETCH);
  fetch.setDataProtocol(DSProtocol.POSTPARAMS);
   
  RestDataSource data=new RestDataSource();  
  data.setOperationBindings(fetch);
  data.setDataFormat(DSDataFormat.JSON);
  data.setFetchDataURL("fetch.php");
  //capturamos la data asincronamente
  data.fetchData(null, new DSCallback(){
   @Override
   public void execute(DSResponse response, Object rawData,
     DSRequest request) {
     
     OnExecuteFetch(response.getData());  
   } 
  }); 
Integración con JQUERY
La integración es bastante sencilla sola haga referencia a los scripts deseados

    
    
El Ejemplo
Normalmente los métodos de Jquery  tienen una función de Callback(Retrollamada) al concluir alguna operación :
$('.tag').hide(“slow”,function(){
  
  alert(‘el tag fue ocultado’)

 });
La idea del ejemplo es mostrar como mediante JSNI podemos llamar al método “hide” y como implementar la función de Callback (Retrollamada) todo dentro de GWT.

Ahora explicaremos algo del código fuente "Jsni.java". En la línea 9 el método “ShowImage” muestra una imagen dada una url, en la línea 16 el método “HideImage” oculta una imagen dada una url , para cumplir con su objetivo hace uso de Jquery con su método “hide” (creando el efecto de ocultamiento)que a su vez realiza una retrollamada (Callback) al ocultar la imagen, al ocultar la imagen lanza la nueva imagen por mostrar llamando al método “ShowImage”.

La integración con PHP podemos verlo en la línea 83, donde se le brinda la ubicación de: “fetch.php”. La data se captura asíncronamente, una vez que la data llega al cliente se lanza el evento “OnExecuteFetch” (en la línea 90).


//Codigo fuente Jsni.java
 
public class Jsni implements EntryPoint {

 private  Image ImgPrincipal=null;
 private VerticalPanel ImgVertical=null;
 
 
   //Mostramos la imagen sin efecto 
 public void ShowImage(String url)
 {
  ImgPrincipal.setUrl(url);
 }
 
   //Ocultamos la imagen con efecto SLOW 
 public native void HideImage(String url)/*-{ 
  var tempThis=this;  
  $wnd.$("#idImgPrincipal").hide('slow',function(){          
    //aca llamamos a Java de JavaScript
    tempThis.@jsni.pck.client.Jsni::ShowImage(Ljava/lang/String;)(url);
    $wnd.$("#idImgPrincipal").show('fast');
  });    
 }-*/;
 
   //Capturamos la imagen snapshot del video
 public native String getImageUrl(String cad)/*-{ 
  //aca llamamos a JavaScript de Java
  return $wnd.$.jYoutube(cad);  
 }-*/;

   //Evento lanzado cuando se ejecuta la Fetch
 public void OnExecuteFetch(Record[] row)
 {
  for(Record tempRow:row){
   
   final String url=tempRow.getAttributeAsString("url");
   String titulo=tempRow.getAttributeAsString("titulo");
   
   HorizontalPanel hp=new HorizontalPanel();
   Image img=new Image(getImageUrl(url));
   img.setSize("50px", "50px");
   
   HTML label=new HTML(titulo);
    label.addClickHandler(new ClickHandler(){ 
     @Override
     public void onClick(ClickEvent event) {
     
      HideImage(getImageUrl(url));
      
     }});
  
   hp.add(img);
   hp.add(label);
   
   ImgVertical.add(hp);
  } 
 }
 
  // Enlaza los Widgets a la Interfaz 
 public void EnlazaInterfaz()
 {
  ImgPrincipal=new Image();
  ImgPrincipal.setSize("250px", "250px");
  
  ImgVertical=new VerticalPanel();
  
  RootPanel.get("idImgPrincipal").add(ImgPrincipal);
  RootPanel.get("idImgVertical").add(ImgVertical);
 }
 public void onModuleLoad() {
  
  //Enlazamos al HTML
  EnlazaInterfaz();
  
  //preparamos para la captura de la data
  OperationBinding fetch = new OperationBinding();
  fetch.setOperationType(DSOperationType.FETCH);
  fetch.setDataProtocol(DSProtocol.POSTPARAMS);
  
  RestDataSource data=new RestDataSource();  
  data.setOperationBindings(fetch);
  data.setDataFormat(DSDataFormat.JSON);
  data.setFetchDataURL("fetch.php");
  //capturamos la data asincronamente
  data.fetchData(null, new DSCallback(){
   @Override
   public void execute(DSResponse response, Object rawData,
     DSRequest request) {
    
     OnExecuteFetch(response.getData());  
   } 
  }); 
 
 }//end function
}//end class
/*
* Codigo fuente de fetch.php
*/
$data=array();
$data[0]['id']=1;
$data[0]['descripcion']='inaguracion en el año 3000';
$data[0]['url']='http://www.youtube.com/watch?v=dz1GpyU6YKQ';
$data[0]['titulo']='INAGURACION SAN FRANK';

$data[1]['id']=2;
$data[1]['descripcion']='inaguracion en el año 2009';
$data[1]['url']='http://www.youtube.com/watch?v=9-FQly3ETP8';
$data[1]['titulo']='INAGURACION SAN JOSE';

$data[2]['id']=3;
$data[2]['descripcion']='inaguracion en el año 2010';
$data[2]['url']='http://www.youtube.com/watch?v=wqE4SdrIu1E';
$data[2]['titulo']='INAGURACION SAN JUMANOR';

$mensaje=array();
$mensaje['response']['status']=0;
$mensaje['response']['data']=$data;

echo json_encode($mensaje);
Los Widgets serán enlazados a los ids: “idImgVertical” y “idImgPrincipal”, como se muestra en el código fuente “Jsni.html”
<!--Codigo fuente Jsni.html-->
<h1>Aplicando JSNI con PHP</h1><table style="width: 605px;" border="1" height="343"><tbody>
<tr><td height="160" width="166"><div id="idImgVertical" style="height: 250px;"></div></td><td width="127"></td>      <td width="290"><div id="idImgPrincipal" style="height: 250px; width: 250px;"></div></td>   </tr>
</tbody> </table>
En este video-guía  se asume que ha creado un proyecto con el nombre “jsni” y paquete “jsni.pck”. Adicionalmente debe de tener instalado GWT 2.0.3 y SmartGWT 2.2. En la carpeta war del proyecto tendrá que crear una carpeta nombrándola como “Scripts” en donde deberá de colocar los archivos “JQuery  1.4.2.js” y “JYouTube.js”.