Canvas y WebGL usando Three.js

canvas
Siguiendo con los post de Canvas. Les mostraré un pequeño ejemplo de la utilización de Three.js, una librería de Canvas y WebGL muy sencilla de implementar.
Lo primero como siempre es importarla entre nuestras etiquetas head de nuestro html.

http://ajax.googleapis.com/ajax/libs/threejs/r67/three.min.js

Y creamos un div dentro de las etiquetas body del html con el id basicMoveWithThree donde se creará nuestro canvas. Además yo le especifiqué un ancho y un alto: style=”width: 600px; height: 400px;”.
Pegaré todo el código de este ejemplo y luego lo explicaré. Lo que haremos será crear un cubo con WebGL el cuál rotará sobre su mismo eje. Este es un ejemplo bastante sencillo, la idea es solo mostrar lo fácil que es utilizar esta librería.

window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded(){
  basicMoveWithThree();
}
function basicMoveWithThree(){
  var scene = new THREE.Scene();
  var camera = new THREE.PerspectiveCamera(25, window.innerWidth/window.innerHeight, 0.1, 1000);
  camera.position.z = 5;

  var renderer = new THREE.WebGLRenderer();
  renderer.setSize(600, 400);
  renderer.setClearColor('#f7f7f7', 1);
  document.getElementById('basicMoveWithThree').appendChild(renderer.domElement);

  var geometry = new THREE.BoxGeometry(1,1,1);
  var material = new THREE.MeshLambertMaterial({color: 'blue'});
  var cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  var ambientLight = new THREE.AmbientLight(0x000044);
  scene.add(ambientLight);      

  var directionalLight = new THREE.DirectionalLight(0xffffff);
  directionalLight.position.set(1, 1, 1).normalize();
  scene.add(directionalLight);

  var angularSpeed = 0.2; 
  var lastTime = 0;
  var render = function(){
    var time = (new Date()).getTime();
    var timeDiff = time - lastTime;
    var angleChange = angularSpeed * timeDiff * 2 * Math.PI / 1000;        
    cube.rotation.x += angleChange;
    cube.rotation.y += angleChange;
    lastTime = time;
    renderer.render(scene, camera);
    requestAnimationFrame(render);
  };

  render();
}

En la primera parte del código cargo la función que contendrá mi script (esto es rutinario de javascript) y llamo a la función basicMoveWithThree declarada más abajo.

window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded(){
  basicMoveWithThree();
}

Ahora ya la parte entretenida. Lo primero que debo hacer es crear una Escena donde si visualizará mi WebGL y es a esta donde se cargarán todos los elementos que vaya creando más adelante, y a su vez crear una cámara que será la perspectiva con la que veré la escena. Hay 3 tipos de cámaras: Camera, OrthographicCamera y PerspectiveCamera. Para este ejemplo usarémos la última, que recibe 4 parámetros:
– El campo de visión vertital de abajo hacia arriba en grados.
– Relación del aspecto del ancho dividido por la altura.
– Plano cercano.
– Plano lejano.
Y luego determino la posición de la cámara en grados.

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(25, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.z = 5;

El paso siguiente es determinar la forma en que se renderizará el Canvas o el WebGL (para este caso será con WebGL), el tamaño del canvas, el color de fondo, la profundidad, la sombra, la gama, etc.
Hay 4 formas de renderizar: CanvasRenderer, WebGLRenderer, WebGLRenderTarget y WebGLRenderTargetCube.
Pero para este caso usaremos WebGLRenderer, con un tamaño de 600 de ancho y 400 de alto, y usé el color de fondo de mi blog #f7f7f7 (por defecto es negro).

var renderer = new THREE.WebGLRenderer();
renderer.setSize(600, 400);
renderer.setClearColor('#f7f7f7', 1);

Junto a crear la forma de renderizar debo especificar donde lo aplicaré, en este caso será a un div con id ‘basicMoveWithThree’.

document.getElementById('basicMoveWithThree').appendChild(renderer.domElement);

Ahora crearemos el cubo. Debemos especificar el tipo de figura que usaremos, estas pueden ser figuras geométricas o curvas. Geométricas pueden ser: BoxGeometry, CircleGeometry, CubeGeometry, CylinderGeometry, ExtrudeGeometry, IcosahedronGeometry, LatheGeometry, OctahedronGeometry, ParametricGeometry, PlaneGeometry, PolyhedronGeometry, RingGeometry, ShapeGeometry, SphereGeometry, TetrahedronGeometry, TextGeometry, TorusGeometry, TorusKnotGeometry y TubeGeometry.
Y los tipos de curvas pueden ser: ArcCurve, ClosedSplineCurve3, CubicBezierCurve, CubicBezierCurve3, EllipseCurve, LineCurve, LineCurve3, QuadraticBezierCurve, QuadraticBezierCurve3, SplineCurve y SplineCurve3.
Y así ya podemos espeficiar el tipo de material (o superficie) del cuál estará compuesto nuestro cubo. Estos pueden ser: LineBasicMaterial, LineDashedMaterial, Material, MeshBasicMaterial, MeshDepthMaterial, MeshFaceMaterial, MeshLambertMaterial, MeshNormalMaterial, MeshPhongMaterial, PointCloudMaterial, RawShaderMaterial, ShaderMaterial, SpriteCanvasMaterial y SpriteMaterial.
Es importante elegir bien el tipo de material de nuestros objetos ya que esto influirá si aplicamos otros aspectos al escenario como la luz. Para este ejemplo usaré MeshLambertMaterial y le pasaré el color azul como parámetro, la clase MeshLambertMaterial puede recibir varios parámetros como intensidad de la luz o la refracción.
Luego creamos el elemento pasandole el elemento geométrico y el material del cuál estará compuesto, para luego agregarlo al escenario definido anteriormente con la función ‘add’.

var geometry = new THREE.BoxGeometry(1,1,1);
var material = new THREE.MeshLambertMaterial({color: 'blue'});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

También podemos trabajar con la luz y su dirección en el escenario. Los tipos de luz que podemos utilizar son: AmbientLight, AreaLight, DirectionalLight, HemisphereLight, Light, PointLight y SpotLight.
Para este ejemplo usaremos AmbientLight recibiendo como parámetro el color de la luz.

var ambientLight = new THREE.AmbientLight(0x000044);
scene.add(ambientLight);  

Y luego especificamos la dirección que tendrá la luz en la escena, también recibiendo el color de la luz.

var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);

El paso final es ejecutar la renderización, y especificar los movientos que queramos realizar sobre los objetos que agregamos a la escena. Podemos utilizar la diferencia del tiempo actual para controlar las revoluciones de rotación de los elementos (en mi caso del cubo). Y luego es importante ejecutar requestAnimationFrame(render); para que el Canvas o WebGL se aplique en forma de frames (se vuelva a llamar).

var angularSpeed = 0.2; 
var lastTime = 0;
var render = function () {
  var time = (new Date()).getTime();
  var timeDiff = time - lastTime;
  var angleChange = angularSpeed * timeDiff * 2 * Math.PI / 1000;        
  cube.rotation.x += angleChange;
  cube.rotation.y += angleChange;
  lastTime = time;
  renderer.render(scene, camera);
  requestAnimationFrame(render);
};
render();

Y así finalmente nuestro WebGL se vería así!

Recuerden que pueden consultar toda la información de la librería en la página oficial y si tienen alguna observación o mejora del ejemplo no duden en comentarla. Saludos!

Matemáticas, física y animación con Canvas html5 – parte 1


canvas
Canvas es una de las cosas que encuentro más interesantes y entretenidas de HTML5, con ella podemos realizar desde gráficos, juegos y un sin fín de cosas sin necesidad de utitilizar ningún plugin en nuestro navegador. Para este ejemplo haremos una pelota (un punto grande) que rebote en contra una pared (caja).
Adjuntaré la librería de Modernizr para garantizar la compatividad en todos los navegadores. Agregando entre las etiquetas head el siguiente código.

<script src="http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.1/modernizr.min.js"></script>

Comenzaré este post escribiendo todo el código para este ejemplo y luego iremos explicando paso a paso lo que tenemos que hacer. Al final del post está el canvas funcionando.
Pegamos el siguiente código en nuestro head entre las etiquetas script del documento html.

window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded(){
  canvasAppPartOne();
}
function canvasSupport(){
  return Modernizr.canvas;
}
function canvasAppPartOne(){
  if(!canvasSupport()){
    return;
  }

  function drawScreen(){
    context.fillStyle = '#EEEEEE';
    context.fillRect(0, 0, theCanvas.width, theCanvas.height);
    context.strokeStyle = '#000000';
    context.strokeRect(1, 1, theCanvas.width-2, theCanvas.height-2);
    ball.x += xunits;
    ball.y += yunits;
    if(ball.x+15 > theCanvas.width || ball.x < 15){       
      angle = 180 - angle;       
	  updateBall();     
    }else if(ball.y+15 > theCanvas.height || ball.y < 15){
      angle = 360 - angle;
      updateBall();
    }
    context.fillStyle = '#000000';
    context.beginPath();
    context.arc(ball.x, ball.y, 15, 0, Math.PI*2, true);
    context.closePath();
    context.fill();
  }
  function updateBall(){
    radians = angle * Math.PI/ 180;
    xunits = Math.cos(radians) * speed;
    yunits = Math.sin(radians) * speed;
  }
	
  var speed = 10;
  var angle = 35;
  var radians = 0;
  var p1 = {x:20,y:20};
  var xunits = 0;
  var yunits = 0;
  var ball = {x:p1.x, y:p1.y};
  updateBall();

  theCanvas = document.getElementById('canvasOne');
  context = theCanvas.getContext('2d');
  setInterval(drawScreen, 33);
}

Luego entre las etiquetas body de nuestro html colocamos el contenedor de nuestro canvas.

<canvas id="canvasOne" width="600" height="300">
  Please update you browser!
</canvas>

Ahora a explicar el código.
Lo primero que hacemos es cargar todo nuestro script en la función load de javascript, para que cuando se cargue la página también lo haga nuestro script.

window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded(){
  canvasAppPartOne();
}

Definimos las variables iniciales de nuestro script. Usaremos la variable speed para determinar la velocidad inicial de la pelota, angle para el ángulo inicial con el cuál se moverá la pelota, radians porque nuestra pelota se moverá en forma de vector con dirección y sentido, y utilizaremos radiales para transformar desde el ángulo, ya que será más legible para nosotros, p1 es la posición inicial de la pelota en la caja, xunits y yunits contendrán la suma que debe aplicarse a la posición de nuestra pelota mientras rebote por la caja, y finalmente ball que será nuestra pelota.

var speed = 10;
var angle = 35;
var radians = 0;
var p1 = {x:20,y:20};
var xunits = 0;
var yunits = 0;
var ball = {x:p1.x, y:p1.y};

Luego referenciamos el elemento DOM en nuestro html, determinamos que trabajaremos bajo un contexto 2d y definimos el intervalo de refresco de nuestro canvas en milisegundos.

theCanvas = document.getElementById('canvasOne');
context = theCanvas.getContext('2d');
setInterval(drawScreen, 33);

La función drawScreen será la encargada de pintar el canvas por cada intervalo que hayamos definido. Lo primero que pintamos es la caja con un borde para poder ver los límites. Las primeras dos lineas pintan el fondo y las dos siguiente pintan el borde.

context.fillStyle = '#EEEEEE';
context.fillRect(0, 0, theCanvas.width, theCanvas.height);
context.strokeStyle = '#000000';
context.strokeRect(1, 1, theCanvas.width-2, theCanvas.height-2);

Ahora con una condición if, vamos podemos saber cuando la pelota choca con los el eje x y el eje y, así podemos cambiar la dirección del vector. En la primera linea si choca con el eje x y en la cuarta linea si choca con el vector y. El número 15 que le sumo a la variable “ball” corresponde radio de la pelota, ya que de no ser así, el borde de la caja chocaría con el centro de la pelota. Fíjese que estoy utilizando la función updateBall(), esta la explicaré un poco más adelante.

if(ball.x+15 > theCanvas.width || ball.x < 15){       
  angle = 180 - angle;       
  updateBall();     
}else if(ball.y+15 > theCanvas.height || ball.y < 15){
  angle = 360 - angle;
  updateBall();
}

Seguidamente dibujamos nuestra pelota que se moverá (o eso parece) por nuestra caja.

context.fillStyle = '#000000';
context.beginPath();
context.arc(ball.x, ball.y, 15, 0, Math.PI*2, true);
context.closePath();
context.fill();

Y ahora fuera de nuestra función drawScreen, definimos la función updateBall. Que se encargará de transformar nuestro cambio en el angulo que hicimos en el if anterior a radiales, con lo que finalmente cambiará la dirección de la pelota.

function updateBall(){
  radians = angle * Math.PI/ 180;
  xunits = Math.cos(radians) * speed;
  yunits = Math.sin(radians) * speed;
}

Y aquí está el resultado.
Espero que les haya servido y si tienen suguerencias para mejorar el código puedes escribirlas!
Saludos!

Actualiza tu browser por la chucha!

 

Cluster en NodeJS con ExpressJS

expressnodejs

Trabajar con Cluster es una excelente forma de mejorar el rendimiento de nuestras aplicaciones. Nodejs es mono-proceso, por lo que no podemos por ejemplo aprovechar de forma eficiente una máquina con varios nucleos. Ahora veremos como hacerlo.
Primero creamos una simple aplicación nodejs con expressjs.

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000);
console.log('Application running!');

Instalamos la librería “cluster”.

sudo npm install cluster

Luego lo que hacemos es levantar un folk (proceso) por cada cpu que tenga nuestra máquina.

var cluster = require('cluster');

if(cluster.isMaster){
  var cpuCount = require('os').cpus().length;
  for(var i = 0; i < cpuCount; i += 1){
    cluster.fork();
  }
}else{
  var express = require('express');
  var app = express();

  app.get('/', function (req, res) {
    res.send('Hello World!');
  });

  app.listen(3000);
  console.log('Application running!');
}

Y listo! Y probar como anda ahora ;)
Ahora bien, si uno de nuestros “trabajadores” muere, podemos reemplazarlo fácilmente.

if(cluster.isMaster){
  ...
  cluster.on('exit', function(worker){
    console.log('Worker ' + worker.id + ' died!');
    cluster.fork();
  });
}else{

Puedes encontrar la documentación completa en la página oficial de Nodejs.
Saludos!

Google Cloud Messaging con NodeJS

google-cloud-messaging

Google Cloud Messaging una de las funcionalidades más lindas que he utilizando en Android, sin tener la necesidad de tener que conectarnos cada vez al servidor, podemos mandar información a través de push a los dispositivos que tengan instalada nuestra aplicación para luego ser tratada, perfecto para notificaciones, ya que ocurre al instante. Ese post no está dedicado a explicar como funciona gcm, si lo desean pueden consultar la documentación oficial de Google para más detalles Google Developer
Entonces lo primero es crear nuestra librería con la cuál nos comunicamos en los servidores de Google, la llamaremos gcm.js

var request = require('request');
var GCM = function(api_key) {
  this._api_key = api_key;
}
GCM.prototype.send = function(msg, callback) {
  request.post({
    uri: 'https://android.googleapis.com/gcm/send',
    json: msg,
    headers: {
      Authorization: 'key=' + this._api_key
    }
  }, function(err, response, body) {
    callback(err, body);
  })
}
module.exports = GCM;

Recuerden que para como estamos importando ‘request’ debemos instalarla en nuestro proyecto con:

sudo npm install request

Paso seguido, creamos la función que determinará a que usuario notificaremos. Importamos el gcm.js que acabamos de crear y reemplazamos las XxxXXXxXxxXxXxXxXXxXxXxXxXxXxXxXxXx por nuestro api key (recuerden que deben dar los respectivos permisos en Google Console), para este ejemplo estoy creando un modulo llamado ‘notify’ que, apoyandome con ExpressJS, recibe a través de una consulta POST el parámetro user_id, luego en un schema llamado ‘User’ busco en mi base de datos un usuario con ese id y obtengo su gcm_id, que había guardado previamente desde el dispositivo del usuario, para poder rutear el mensaje que deseo enviar.

var GCM = require('./gcm.js');
var gcm = new GCM('XxxXXXxXxxXxXxXxXXxXxXxXxXxXxXxXxXx');

exports.notify = function(req, res){
  var user_id = req.body.user_id;
  User.findOne({_id: user_id}, function(err, user){
    if(!err && user){
      var msg = {
        registration_ids: [user.gcm_id],
        collapse_key: "your_collapse_key",
        time_to_live: 180,
        data: {
          message: 'Este es mi mensaje!'
        }
      };
      gcm.send(msg, function(err, response){
        console.log(response);
        res.send(response.success);
      });
    }else{
      res.send('false');
    }
  });
}

Y listo! Una implementación bastante sencilla de Google Cloud Message en NodeJS.
Saludos!

Genymotion con Google Apps

genymotion

Hace un tiempo que estoy utilizando la versión community (free) de Genymotion y una de las limitantes con las que me encontré es que no pude usar los servicios de Google, como los mapas, mensajería gcm, etc. He aquí la solución!

Primero bajamos este archivo:
ARM Translation Installer v1.1 (Mirror)
y sin descomprimirlo lo arrastramos sobre nuestra ventana de VM de Genymotion iniciada (si arrastrar sobre la ventana!).

Luego bajando la Google Apps según la versión de Android que estemos utilizando
Google Apps for Android 4.4 (Mirror)(Download from CM11 Links)
Google Apps for Android 4.3 (Mirrors)
Google Apps for Android 4.2
Google Apps for Android 4.1
y también arrastramos sobre la ventana de VM Genymotion iniciada.
Ahora reinicias y ya podrás acceder a Google Play y a sus servicios!
Saludos!

Calcular distancia entre dos coordenadas en javascript #nodejs

javascript_logo_unofficial-300x300

Esta función siempre está en mis proyectos donde utilizo coordenadas georeferencias (latitud y longitud), casi todos ellos son proyectos para dispositivos móviles.
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
  var R = 6371;
  var dLat = (lat2-lat1) * (Math.PI/180);
  var dLon = (lon2-lon1) * (Math.PI/180);
  var a =
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(lat1 * (Math.PI/180)) * Math.cos(lat2 * (Math.PI/180)) *
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ;
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c;
  return d;
}
Retorna la distancia en kilómetros.
Saludos!

Carga de archivos en Amazon S3 desde NodeJS

nodejs   amazon

Hace muchísimo tiempo que no escribo nada aquí!, me consumió el mundo Enterprise :( pero ya estoy libre!. Ahora a lo que nos compete. Esta guía no trata del funcionamiento de Amazon S3 ni de NodeJS, ojo con eso. Comenzamos!
Primero a través de nuestra terminal instalamos la librería para conectarnos a Amazon S3
npm install aws-sdk
Luego en nuestro archivo .js importamos la librería y la configuramos con nuestras credenciales de acceso. Para finalmente crear la instancia s3 que utilizaremos para accesar al S3 de Amazon.
var aws = require('aws-sdk');
aws.config.update({
    accessKeyId: 'XXXXXXXXXXXXXXXXXXXX',
    secretAccessKey: 'XXxxXxXXXxxxXxXXXxXXxxXXxxXXXxxxx'
});
var s3 = new aws.S3();
Ahora ya podemos listar nuestros buckets.
s3.listBuckets(function(err, data){
    for(var index in data.Buckets){
        var bucket = data.Buckets[index];
        console.log("Bucket: ", bucket.Name, ' : ', bucket.CreationDate);
    }
});
Y insertar una nueva imagen. Para estos casos yo siempre mando la imagen en base64, entonces antes de guardarla en el S3 tengo que meterla a un Buffer
var image = req.body.image;
var buff = new Buffer(image.replace(/^data:image\/\w+;base64,/, ""),'base64');
Creo una variable con los parámetros para el putObject
var params = {
    Bucket: 'nombre_bucket',
    Key: 'nombre_imagen.png',
    Body: buff,
    ACL: 'public-read'
};
Un parámetro importante en la linea anterior es ACL, ‘public-read’ permite que la imagen pueda ser (como su nombre lo dice) pública.
s3.putObject(params, function(err, data){
    if(!err){
        console.log('load ok');
    }else{
        console.log('load fail');
    }
});
Y si es un archivo que tienen en su disco
var params = {Bucket: 'myBucket', Key: 'nombre_archivo.png'};
var file = require('fs').createWriteStream('/path/to/file.jpg');
s3.getObject(params).createReadStream().pipe(file);
Y eso es todo!
Comentarios y sugerencias son totalmente bienvenidos, saludos!

Pyramid framework en OpenShift

Pyramid es un framework de python para desarrollar aplicaciones web. Sus fuertes son la velocidad, flexibilidad y escalabilidad que ofreces a los desarrolladores. No es un full-stack framework (Full-Stack: el objetivo principal de los full-stack es proveer un conjunto de componentes que abarque todo lo que necesitas para construir una aplicación web, asegurandose que todos esos componentes funcionen bien entre si.) como Django y no es un microframework como Flask o Bottle. Y a su vez OpenShift es una plataforma deployar aplicaciones en la “nube” (algo así como heroku, cloudcontrol, phpfog, Amazon, etc.) bajo la infraestructura de Red Hat. Openshift permite integrar (sin necesidad de otro servicio) base de datos en MySQL, MongoBD, PostgreSQL, etc.

Requisitos para esta guía:

- Linux Fedora (es un requisito por los repositorios, pero si utilizan otra distribución no hay problema).
- Cuenta en Open Shift.
- Habilitar base de datos MySQL en consola de aplicaciones en Open Shift

Lo primero es registrarnos en Open Shift http://openshift.redhat.com.
Luego creamos nuestra aplicación en la administración de aplicaciones y en el momento de seleccionar el lenguaje a utilizar, seleccionamos Python (obvio o no? xD ).

La configuración de la aplicación en OpenShift no es parte de esta guía, asi que lo saltaremos. Si no saben como utilizar Open Shift les recomiendo utilizar la documentación disponible en el mismo sitio, y las guías de instalación en diferentes sistema operativos.

Ahora los pasos que realmente nos interensan.

Instalamos git como controlador de versiones (Requisito para modificar el código de nuestra aplicación).

yum install git

Recuerden agregar su llave pública en la consola de administración de aplicaciones en el sitio de Open Shift.

Instalamos las herramientas de clientes de Open Shift. Con esta herramienta se pueden administrar el estado de las base de datos de nuestras aplicaciones, crear nuevas aplicaciones, etc.
Según la distribución de linux que tengamos, el nombre del paquete puede cambiar.

yum install rubygem-rhc

Descargamos nuestro código fuente (reemplazar por su repositorio).

git ssh://xxXXxxXXxXXxXXXxxx@xxxxx-xxxx.rhcloud.com/~/git/xxxxxx.git/

Si no hemos instalado la base de datos mysql, lo hacemos ahora. (Esta tarea también se puede realizar a través del administrador de aplicaciones de Open Shift). Es importante reemplazar el nombre del proyecto y el email por el mismo que utilizaron al crear su cuenta de Open Shift.

rhc-ctl-app -a nombreproyecto -e add-mysql-5.1 -l your@email.com

Tenemos diversas opciones para administrar nuestra base de datos:

rhc app cartridge start -a nombreproyecto -c mysql-5.1
rhc app cartridge stop -a nombreproyecto -c mysql-5.1
rhc app cartridge restart -a nombreproyecto -c mysql-5.1
rhc app cartridge reload -a nombreproyecto -c mysql-5.1
rhc app cartridge status -a nombreproyecto -c mysql-5.1
rhc app cartridge remove -a violeta -c mysql-5.1

Entramos al directorio del proyecto.

cd nombreproyecto

Hacemos la referencia a pyramid.

git remote add upstream -m master git://github.com/lmacken/pyramid-openshift-quickstart.git

 

git pull -s recursive -X theirs upstream master

Y finalmente guardamos.

git push

Eso es todo, espero haya servido esta guía y si quieren aportar algo bienvenido sea.
Recuerden visitar nuestra comunindad de Python Chile y participar en nuestros MeetUp

Carga de archivos en Amazon S3 con PHP

Amazon S3 es almacenamiento para Internet. Está diseñado para facilitar a los desarrolladores la informática a escala web.

Amazon S3 proporciona una sencilla interfaz de servicios web que puede utilizarse para almacenar y recuperar la cantidad de datos que desee, cuando desee, y desde cualquier parte de la web. Concede acceso a todos los desarrolladores a la misma infraestructura económica, altamente escalable, fiable, segura y rápida que utiliza Amazon para tener en funcionamiento su propia red internacional de sitios web. Este servicio tiene como fin maximizar las ventajas del escalado y trasladar estas ventajas a los desarrolladores (descripción por Amazon).

¿Qué necesitamos?
- Una cuenta en amazon S3
- Librería de S3 de Amazon que pueden descargar aquí: S3.php
- PHP

Para este ejemplo armaremos sólo 1 archivo, con el fin de simplificar la guía. Entonces comencemos!

vim index.php

Comenzamos importando la librería S3 q se especifica más arriba

// Incluimos la clase de Amazon S3
if(!class_exists('S3'))require_once('S3.php');

Definimos las keys de acceso, estás están especificados en la información de nuestra cuenta en AWS

// Informacion de acceso al AWT
if(!defined('awsAccessKey')) define('awsAccessKey', 'XXXXXXXXXXXXXXXXX');
if(!defined('awsSecretKey')) define('awsSecretKey', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');

Instanciamos la clase S3 para hacer la conección con Amazon

// Instanciamos la clase de S3
$s3 = new S3(awsAccessKey, awsSecretKey);

Definimos nuestro bucket o almacen de archivos (previamente creado en AWS)

// Nombre del Bucket en Amazon S3
$bucket = "XXXXXXX";

Luego con un formulario enviamos el archivo que deseamos cargar

// Cuendo presiono el boton Upload
if(isset($_POST['Submit'])){
// Recibo las variables por POST
$fileName = $_FILES['theFile']['name'];
$fileTempName = $_FILES['theFile']['tmp_name'];
// Creo un nuevo bucket de Amazon S3
$s3->putBucket($bucket, S3::ACL_PUBLIC_READ);
// Muevo el archivo de su ruta temporal a su ruta definitiva
if($s3->putObjectFile($fileTempName, $bucket, $fileName, S3::ACL_PUBLIC_READ)) {
      echo "Archivo subido correctamente.";
}else{
      echo ""No se pudo subir el archivo.";
}
}

Creamos nuestro formulario

<form action="" method="post" enctype="multipart/form-data" name="form1" id="form1">
 <input name="theFile" type="file" />
 <input name="Submit" type="submit" value="Upload">
 </form>

Listamos los archivos en nuestro Bucket en Amazon S3

<h1>Lista de archivos en el S3</h1>
<?php
 // Listamos el contenido del Bucket de Amazon S3
 $contents = $s3->getBucket($bucket);
 foreach ($contents as $file){

$fname = $file['name'];
 $furl = "http://".$bucket.".s3.amazonaws.com/".$fname;

// Imprimo el archivo que voy encontrando
 echo "<a href=\"$furl\">$fname</a><br />";

 }
?>

Puedes descargar el archivo completo ejemplo_php_amazons3

Saludos y gracias por su visita!

Geocodificación en Ruby con Geocoder

  

La geolocalización y la geocodificación hoy cumplen un papel fundamental en la composición de nuestras aplicaciones. Determinar el pais, la ciudad, el lenguaje, etc sin duda que agregar un gran valor a la hora de personalizar aplicaciones para nuestros visitantes.

Comencemos!

Para esta entrada utilizaré:
- Fedora 16
- Ruby 1.8.7
- Rubygems 1.8.11
- Geocoder 1.1.0
- json_pure 1.6.4

La versión de Ruby 1.8.7 y Rubygems 1.8.11 es la trae por defecto el repositorio de Fedora 16.

sudo yum install ruby rubygems

Ahora instalamos Geocoder y su dependencia json_pure

sudo gem install geocoder json_pure

Podemos forzar las versiones que desamos instalar de la siguiente forma

sudo gem install -v=1.1.0 geocoder

Ya está listo nuestro Ruby con sus gemas necesarias, Geocoder nos instala un script para realizar peticiones por terminal, este lo podemos utilizar de la siguiente forma

$ geocode "Quilicura, Santiago"

# Resultado:
# Latitude:         -33.3613271
# Longitude:        -70.7287415
# Full address:     Quilicura, Santiago Metropolitan Region, Chile
# City:             Quilicura
# State/province:   Santiago Metropolitan Region
# Postal code:      
# Country:          Chile
# Google map:       http://maps.google.com/maps?q=-33.3613271,-70.7287415

Ya funcionando podemos crear nuestros primero ejemplos, entonces creamos un archivo .rb

vim ej_geocoder1.rb

Con el siguiente contenido

# Importamos nuestras gemas, recuerden que en versiones de ruby 1.8 se debe importar siempre la gema 'rubygems'.
require 'rubygems'
require 'geocoder'

# Realizamos una busqueda, esto nos devolvera un lista de coincidencias y con [0] decimos que queremos la primera.
local = Geocoder.search("Quilicura, Santiago, Chile")[0]

# Imprimimos las coordenadas de la direccion buscada
puts local.coordinates

Ejecutamos

ruby ej_geocoder1.rb

Geocoder.search devuelve un objeto con lo siguientes atributos:
address
address_components
address_components_of_type(type)
city
coordinates
country
country_code
formatted_address
geometry
postal_code
state
state_code
types

Entonces siguiendo el ejemplo anterior podemos obtener el pais de nuestra busqueda de la siguiente forma

local.country

También con Geocoder podemos obtener la dirección de una ip o de unas coordenadas de la siguiente forma

vim ej_geocoder2.rb
# Importamos nuestras gemas necesarias
require 'rubygems'
require 'geocoder'

# Ingresamos la ip que queremos buscar y la primera coincidencia con el valor [0]
ip = Geocoder.search("200.113.190.187")[0]
puts ip.address
puts ip.coordinates

# Obtenemos la direccion a traves de unas coordenadas
ip = Geocoder.search("-33,-70")[0]
puts ip.address

Ejecutamos

ruby ej_geocoder2.rb

Geocoder se provee de buscadores como Google, Yahoo, Bing, GeocoderCa, etc para realizar sus busquedas. Esto podemo configurarlo en:

/usr/lib/ruby/gems/1.8/gems/geocoder-1.1.0/lib/geocoder/configuration.rb

en la propiedad [:lookup, :google] , recuerden que la url puede variar según las versiones instaladas.

Más información en la página oficial en RubyGeocoder

Gracias por su visita!

Astrometría en Python con PyEphem


  

Uno de mis hobbies es la Astronomía y eso me ha llevado a investigar las herramientas que existen actualmente para realizar cálculos de Astrometría. Leyendo en internet y también por recomendación de amigos decidí utilizar Python para este entrada, por sus avances en materias científicas en relación a otros lenguajes de desarrollo.

Sin ningún fin es particular decidí utilizar PyEphem para ejemplificar la utilización de Astromería en Python. PyEphem es un módulo para realizar cálculos astronómicos tales como posiciones de astros, planetas, horas de orto y ocaso de los astros, etc. También se puede calcular la posición de cometas, asteroides y satélites una vez proporcionados los elementos orbitales de los mismos.

Comencemos! Para este ejemplo utilizo una distribución basada en Red Hat, pero pueden utilizar la que deseen, aunque los nombres de los paquetes pueden variar sutilmente.

Porsupuesto lo primero que debemos verificar, son los paquetes necesarios: python, python-devel para las herramientas de desarrollo y gcc para la compilación de pyephem.

sudo yum install python python-devel gcc

Luego a través del gestor de paquetes de python easy_install instalamos otro gestor llamado pip.

sudo easy_install pip

Y finalmente instalamos PyEphem.

sudo pip install pyephem

Y ahora un ejemplo de utilización.

vim ejemplo_pyephem1.py
# Importamos la libreria de PyEphem
import ephem as ep

# Creamos un objeto Martes, ep.now() hace referencia a este momento
martes = ep.Mars(ep.now())

# Imprimimos la constelacion en la cual se encuentra Martes en pantalla
print ep.constellation(martes)

Ejecutamos.

python ejemplo_pyephem1.py

Otro ejemplo para soltar más la muñeca

vim ejemplo_pyephem2.py
#Importamos nuestra libreria
import ephem as ep

# Creamos un observatorio ubicado en Santiago.
# Podemos agregar y modificar las coordenadas de nuestras ciudades en:
# /usr/lib64/python2.7/site-packages/ephem/cities.py
santiago = ep.city("Santiago")

# Obtenemos la fecha actual de Santiago
santiago.date = ep.now()
print "Fecha hoy: ", santiago.date

# Anulamos la Refraccion atmosferica
santiago.pressure = 0 

# Creamos un objeto Martes y uno Saturno en el observatorio de Santiago.
martes = ep.Mars(santiago)
saturno = ep.Saturn(santiago)

# Imprimimos la altura y azimut desde el Observatorio de Santiago.
print "Martes: ", martes.alt
print "Saturno: ", saturno.alt

# Imprimimos la separacion entre ambos planetas 
print "Separacion entre Martes y Saturno", ep.separation(martes,saturno)

# Proxima luna llena en el observatorio de Santiago
print "Luna llena: ", ep.next_full_moon('2012')

Ejecutamos.

python ejemplo_pyephem2.py

Más información en la página oficial de PyEphem.

Recuerden visitar nuestra comunidad de Python Chile!

Primeros pasos en Pypy


Pypy es una rápida y potente alternativa de implementación de Python 2.7.1+, la cuál nos ofrece variadas ventajas y caracteristicas que la diferencian de otras impelentaciones.

Velocidad: Gracias a su Just-in-time compilador, los programas en Python suelen correr más rápido en Pypy. JIT: En informática, la compilación en tiempo de ejecución (también conocida por sus siglas inglesas, JIT, just-in-time), también conocida como traducción dinámica, es una técnica para mejorar el rendimiento de sistemas de programación que compilan a bytecode, consistente en traducir el bytecode a código máquina nativo en tiempo de ejecución. La compilación en tiempo de ejecución se construye a partir de dos ideas anteriores relacionadas con los entornos de ejecución: la compilación a bytecode y la compilación dinámica. Más información aquí.
Uso de memoria: Gran consumo de memoria de programas Python podría terminar tomando menos espacio que lo hacen en CPython.
Compatibilidad: Pypy es altamente compatible con el código existente Python. Es compatible y puede funcionar bibliotecas ctypes populares de Python como Django.
Sandboxing: Pypy ofrece la posibilidad de ejecutar código no firmado de forma totalmente segura.
Stackless: Pypy puede ser configurado para ejecutarse en el modo de Stackless, proporcionando micro-temas de concurrencia masiva.

Comenzamos con la instalación.
Primero debemos reparar nuestra máquina instalando las siguientes librerias:

En Fedora

$ sudo yum install gcc make python-devel libffi-devel pkg-config zlib-devel bzip2-devel ncurses-devel expat-devel openssl-devel gc-devel python-sphinx python-greenlet

En Ubuntu

$ sudo apt-get install gcc make python-dev libffi-dev pkg-config libz-dev libbz2-dev libncurses-dev libexpat1-dev libssl-dev libgc-dev python-sphinx python-greenlet

Luego instalamos pypy. Esto podemos realizarlo desde el sitio web aquí

o con los gestores de paquetes de Unix:

En Fedora

$ sudo yum install pypy pypy-devel pypy-libs

y en Ubuntu

$sudo apt-get install pypy pypy-dev

Si descargamos el de forma manual hacemos lo siguiente:

Descomoprimimos el archivo

$ tar -xvf pypy1.7 pypy1.7.tar.bz2

Lo movemos a la carpeta que corresponde

$ sudo mv pypy1.7 /opt/

Y por último creamos un enlace simbolico para que pueda utilizarse en nuestro bash

$ sudo ln -s /opt/pypy-1.7/bin/pypy /usr/local/bin/pypy

Y con esto ya está listo para utilizar!

[pablo@tuidee ~$] pypy

En mi caso tuve problemas con el versionado de algunas librerías, ya que al momento de ejecutar con comando pypy en la terminal me arrojaba el siguiente error:

[pablo@tuidee ~$] pypy
pypy: error while loading shared libraries: libssl.so.0.9.8: cannot open shared object file: No such file or directory
pypy: error while loading shared libraries: libcrypto.so.0.9.8: cannot open shared object file: No such file or directory
pypy: error while loading shared libraries: libbz2.so.1.0: cannot open shared object file: No such file or directory

Esto lo solucioné de la siguiente forma:
En Fedora 32 bit

$ sudo ln -s /usr/lib/libssl.so.10 /usr/lib/libssl.so.0.9.8
$ sudo ln -s /usr/lib/libcrypto.so /usr/lib/libcrypto.so.0.9.8
$ sudo ln -s /usr/lib/libbz2.so /usr/lib/libbz2.so.1.0

En fedora 64 bits

$ sudo ln -s /usr/lib64/libssl.so.10 /usr/lib64/libssl.so.0.9.8
$ sudo ln -s /usr/lib64/libcrypto.so /usr/lib64/libcrypto.so.0.9.8
$ sudo ln -s /usr/lib64/libbz2.so /usr/lib64/libbz2.so.1.0

En Ubuntu se puede realizar a través del gestor de paquetes::

$ sudo apt-get install libssl0.9.8:i386

ya conocen el resto de los comandos necesarios para solucionarlo.

Recuerden verificar la versión de las librerias que necesitan, ya que pueden variar.

Y porsupuesto visiten la página web oficial de Pypy aquí.

Saludos y pronto continuaré con un pequeño ejemplo de utilización.

Guía básica utilización de JRuby

 

No es novedad la potencia y rendimiento que posee la máquina virtual de Java, pero tampoco lo es lo tedioso que resulta desarrollar sobre esta misma. Es así entonces como nace la mezcla perfecta de un luega dinamico como ruby y el gran rendimiento de jvm!

Entonces… qué necesitamos?
- JRuby
- Java SDK

Para fedora, redhat, centos:

sudo yum install jruby

Ubuntu y deribados:

sudo apt-get install jruby

Si estamos cometiendo el pecado de no utilizar una máquina con Unix lo descargamos de aquí.

Y también descargamos la última versión de java SDK. Recomendamos Java 7.

sudo yum install java-sdk

o

sudo apt-get install java-sdk

Si no poseemos un repositorio de java lo descargamos directamente del sitio de Oracle aquí.

Ahora ya estamos listos para comenzar.

Primero creamos un archivo para extraer datos (para hacer la cosa un poquito más interensate)

echo "Hola Mundo !!" >> datos.txt

Creamos nuestro archivo ruby

vim primerJRuby.rb

Y pegamos lo siguiente

require 'java'
module JavaIO
   include_package "java.io"
end
frame = javax.swing.JFrame.new("Mi primer JFrame en JRuby")
frame.size = java.awt.Dimension.new(400,200)
label = javax.swing.JLabel.new((File.open('datos.txt', 'r')).readline)
frame.getContentPane.add(label,java.awt.BorderLayout::CENTER)
frame.setDefaultCloseOperation(javax.swing.JFrame::EXIT_ON_CLOSE)
frame.setVisible(true)

Explicación…

Importamos java

require 'java'

Importamos la libreria java.io para aceptar entradas IO

module JavaIO
include_package "java.io"
end

Creamos nuestro frame (ventana)

frame = javax.swing.JFrame.new("Mi primer JFrame en JRuby")

Le asignamos tamaño a nuestra ventana

frame.size = java.awt.Dimension.new(400,200)

Leemos un archivo y lo desplegamos a través de un label

label = javax.swing.JLabel.new((File.open('datos.txt', 'r')).readline)

Meto el label dentro del JFrame

frame.getContentPane.add(label,java.awt.BorderLayout::CENTER)

Le asigno la funcionalidad de cerrar al JFrame

frame.setDefaultCloseOperation(javax.swing.JFrame::EXIT_ON_CLOSE)

Hacemos visible nuestro JFrame

frame.setVisible(true)

y ejecutamos.

jruby primerJRuby.rb

Espero les haya servido.
Saludos!

Ruby on Rails + Cassandra DB en Linux Ubuntu

Estimandos, continuando con las guías entretenidas: Seguimos con el simpático lenguaje de desarrollo Ruby y su framework Rails. Y para hacerlo más entretenido aún implementaremos la base de datos no relacional (noSQL) Cassandra, dicha base de datos fué creada por facebook, pero al poco tiempo pasó a las manos de Apache Fundation en la cual se desarrolló y desarrolla hasta convertirse en lo que es hoy. En esta guía básica utilizaremos la versión 0.8.4 de Cassandra. Comencemos!.

Para los propósitos de esta guía, necesitamos:

- Linux Ubuntu.

- Conección a internet

- y llevar lo ñoñez en la sangre!

 

Ruby on Rails

Primero instalamos Ruby, aplicando la magia de ubuntu…

sudo apt-get install ruby

Seguimos con su framework Rails (necesitamos el cargador de gemas de Ruby y el interprete irb):

sudo apt-get install irb
sudo apt-get install rubygems
sudo gem install rails -–include-dependencies

Y para no perder la linea, creemos de inmediato un proyecto:

rails new primerProyecto

Nos generará una larga lista de de directorios y archivos.

Los que nos interesan como referencia básica son:

cd primerProyecto
app/controllers
app/views
script/rails
 

Entonces creamos nuestro controlador

ruby script/rails generate controller Home index

El cual también generará un par de archivos, donde:

script/rails : es el script escrito en ruby que realizará el procedimiento de generación los archivos.

generate : es la acción a realizar.

controller : es el tipo de archivos que queremos generar.

Home : es el nombre del controlador que se generará.

index : es el método que vamos a crear dentro del controlador, si quisiéramos generar más, basta con ir escribiéndolos separados con un espacio.

 

Abrimos nuestro controlador:

(Yo utilizo “vim” como editor de consola, utilicen el que deseen)

vim app/controllers/home_controller.rb

Nos encontramos con una estructura así:

class HomeController < ApplicationController
        def index
        end
end

Tengo 2 formas de comentar codigo, una es con un # ante de la linea y para comentar parrafos debo hacerlo con

#Esta es mi forma de comentar
#de una sola linea

=begin
Aquí va mi texto comentado
en forma de párrafo
en varias lineas
=end

Creamos una función index, que por defecto es la primera función que se ejecuta entrar al controlador:

Ojo con las comillas, porque si copian y pegan pueden tener problemas, recomiendo escribirlas manualmente.

class HomeController < ApplicationController
    # Controlador que se ejecuta por default
    def index
        # render:text escribe un texto en pantalla sin la necesidad de crear una vista (views) explicitamente
        render:text => “Hola Mundo!”
    end
end

Ahora si quiere utilizar el controlador más la vista, lo hacemos de la siguiente forma

class HomeController < ApplicationController
    # Controlador que se ejecuta por default
    def index
        @nombre => “Mi nombre es Pablo Araya<br />”
        @ubicacion => “Santiago, Chile”
    end
end

Abrimos nuestra vista

vim app/views/home/index.html.erb

Deberíamos verla así

<h1>Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p>

y lo dejamos así:

 <h1>Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p> 
<%= "Mi nombre es "+nombre+" y vivo en "+ubicacion %>

el codigo ruby va entre estas etiquetas

<%
# Aqui nuestro codigo
%>

si queremos imprimer algo en el navegador agregamos el signo =

<%= variable %>

 

Ahora es el turno de Cassandra

Bajamos la última versión de Cassandra: http://cassandra.apache.org/#download o en consola:

wget http://apache.freeby.pctools.cl//cassandra/0.8.4/apache-cassandra-0.8.4-bin.tar.gz

Lo descomprimimos, lo renombramos a cassandra y lo movemos al directorio /opt:

tar xzvf apache-cassandra-0.8.4-bin.tar.gz
mv apache-cassandra-0.8.4-bin cassandra
sudo mv cassandra /opt/

Creamos los directorios que la aplicación necesita:

sudo mkdir -p /var/lib/cassandra/{commitlog,data,callouts,staging}
sudo mkdir /var/log/cassandra
sudo chmod -R 777 /var/lib/cassandra/

Creamos el fichero /var/log/cassandra/system.log y le damos permisos de escritura:

touch /var/log/cassandra/system.log
sudo chmod 777 /var/log/cassandra/system.log

Necesitamos crear nuestra estructura de base de datos, ya que Cassandra es un motor no relacional, su estructura parece grandes columnas o arreglos bidimensionales.

Ahora ya podemos levantar Cassandra, de forma default o definiendo parametros.

/opt/cassandra/bin/cassandra -f &
/opt/cassandra/bin/cassandra-cli -host localhost -port 9160

Lo entretenido de esta guía es hacer que estos dos sistemas interactuen, asi que nos vamos a nuestro controlador:

vim app/controllers/home_controller.rb

Y lo dejamos de la siguiente forma:

# Traigo mi gema cassandra para realizar la conexion
require 'cassandra'
class HomeController < ApplicationController
    # Controlador que se ejecuta por default
    def index
        =begin
        Creo mi nueva conexion con Cassandra.new('Espacio de trabajo','ip servidor')
        Si tengo ruby y cassandra en el mismo servidor, puedo omitir la ip
        =end
        store = Cassandra.new('Keyspace1')
        @nombre => “Mi nombre es Pablo Araya<br />”
        @ubicacion => “Santiago, Chile”
    end
end

Continua..

Guía Básica de JQuery Mobile

Estimados visitantes, JQuery Mobile es un framework que integra JQuery y está optimizado para realizar sitios web para dispositivos móviles touch.

Las carácteristicas de JQueryMobile son:
- Facilidad de uso: Otorga mucha facilidad para el desarrollo de interfaces de usuario de dispositivos móviles.
- Soporte HTML5 markup-driven: Cuando utilicemos este framework, nos olvidaremos de tipear código JavaScript. Gracias al uso de etiquetas HTML, que luego en el momento de renderizado serán procesadas por Jquery Mobile
.- Múltiples plataformas soportadas: JQuery soporta muchos dispositivos y tecnologías, como ser: IOS, Android, Blackberry, Palm WebOS, Symbian, Windows Mobile, etc.
- Tamaño reducido: Toda la librería comprimida pesa menos de 12K.
- Temas personalizados: El framework expone algunas utilidades para el manejo de temas y también es posible crear temas propios.

Por supuesto lo primero que debemos hacer es importar las librerías necesarias dentro de las etiquetas <head></head> de nuestro sitio web, la de JQuery, JQueryMobile y CSS con los themes del framework.

Nota: Al momento de realizar esta guía la última versión de JQuery era 1.6.1 y JQueryMobile 1.0b. Es recomendable descargar las librerías y subirlas en nuestro sitio web.

<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.css" />
<script src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"></script>

La etiqueta <meta></meta> es muy importante ya que determina el tamaño del dispositivo movil.

Dentro de la etiqueta <body>, cada vista o “página” en el dispositivo móvil se identifica con un elemento (normalmente un div) con los data-role=”page” de atributos:

<div data-role=”page”>
Tú contenido...
</div>

Dentro de la “página” de contenedores, cualquier código HTML válido puede ser utilizado, pero para las paginas de JQueryMobile los “divs” dentro deben ser header, content y footer:

<div data-role="page">
<div data-role="header">...</div>
<div data-role="content">...</div>
<div data-role="footer">...</div>
</div>

En JQueryMobile podemos tener varias páginas dentro de un mismo archivo HTML, navegando sin tener q recargar un sitio. Para lograr esto necesitamos identificar los diferentes div que contengamos con un identificador único para los tipo “page”, es decir:

<div data-role="page" id="home">...</div>
<div data-role="page" id="login">...</div>
<div data-role="page" id="register">...</div>

Además, en cualquier parte del sitio se pueden desplegar “dialogos”, agregando data-rel=”dialog” a un enlace y el framework automáticamente oscure el fondo y redondea los bordes para darle el estilo del sitio.

<a href="dialogo.html" data-rel="dialog">Abrir dialogo</a>

Nota: Para cerrar la ventana de dialogo puede hacerlo mediante el atributo data-rel=”back” en un enlace refenciado a “#” o con la función $(‘.ui-dialog’).dialog(‘close’) de JQuery.

El efecto de transición al cambiar de vista por defecto es “pop” pero podemos especificar el que deseemos, ya sea “flip”, “slipdown”, “pop” y entre otros que podemos encontrar en la documentación oficial de JQueryMobile.

<a href="dialogo.html" data-rel="dialog" data-transition="pop">Abrir dialogo</a>

Por defecto, los botones de expanden al ancho de la ventana, pero podemos solucionar esto anidando los botones dentro de un div con el atributo <div data-inline=”true”>

<div data-inline="true">
<a href="index.html" data-role="button">Cancelar</a>
<a href="index.html" data-role="button">Aceptar</a>
</div> 

Incluso podemos agrupar botones:

<div data-role="controlgroup">
<a href="index.html" data-role="button">Si</a>
<a href="index.html" data-role="button">No</a>
<a href="index.html" data-role="button">Aveces</a>
</div>

Podemos definir distintos diseños (o themes) a toda la variedad de elementos que componen cada una de nuestras vistas, simplemente agregando el atributo data-theme=”a”. JQueryMobile dispone de 5 themes para nuestros desarrollos: a,b,c,d,e.

<a href="index.html" data-role="button" data-theme="a">Boton</a>

Para organizar nuestros elementos dentro de cada vista, podemos organizarlos en grillas o columnas, esto lo hacemos de la siguiente forma:

<div class="ui-grid-b">
<div class="ui-block-a">Block A</div>
<div class="ui-block-b">Block B</div>
<div class="ui-block-c">Block C</div>
</div>

Y finalmente te invito leer la documentación oficial de JQueryMobile ya que aún existen muchas mas funcionalidades que este framework te puede entregar. Esperando cumplir con las expectativas de los nuevos usuarios que pretenden iniciarse con esta herramienta, me despido.

-