Geocodificación II. Geocodificando del lado cliente con javascript.

Si en la anterior entrada tratamos la geocodificación en el lado del servidor, ahora toca pensar en que no hay motivo para agobiar a nuestro servidor haciendo algo que puede hacer el navegador del cliente.

Para ello vamos a hacer otra pequeña aplicación haciendo uso de la API javascript de google maps v3, donde un usuario simplemente rellena un formulario con los datos de su domicilio, gracias a los cuales geocodificamos sus coordenadas para almacenarlas. Y para dar un plus de seguridad al proceso, antes de la validación final, se marca con una chincheta en un mapa las coordenadas para que el usuario confirme que, efectivamente, esa es la localización de su domicilio.

Esto es una buena costumbre porque los servicios no son perfectos. Un error de 20 o 30 metros a veces ocurre, y suele ser aceptable, pero a veces que existen dos calles con el mismo nombre en localidades distintas de la misma provincia, con errores de kilómetros. Me sucedió una vez con dos calles que se llamaban igual en A Coruña y Ferrol, y como A Coruña google puede interpretarlo como localidad o como provincia, supongo que de ahí venía el error.

Empecemos creando la aplicación y generando un usuario con los campos nombre, dirección, Provincia, y País.

rails new geocodificacion_js
cd geocodificación
/* En este punto, configuro HAML como explique aqui hace dos o tres entradas */
rails g scaffold user nombre:string direccion:string provincia:string pais:string lat:float lng:float
rake db:migrate
rails s

Tenemos también que crear en el fichero config/locales/en.yml unas entradas para la traducción, sino los mensajes que aparecerán en el navegador serán bastante feos. Copiando estas lineas es suficiente.

en:
  edit: "Edit"
  show: "Show"
  destroy: "Destroy"
  back: "Back"
  actions: "Actions"
  are_you_sure: "are you sure?"
  users:
    index:
      title: "Users index"
      new_user: "New user"
    show:
      title: "Show user"
    edit:
      title: "Edit user"
    new:
      title: "New user"

De acuerdo. Tenemos la aplicación. Ahora toca insertar un mapa de google maps en el formulario de nuevo usuario. No os asuste lo más mínimo, hacerlo es muy sencillo. Id al fichero donde está ese formulario, normalmente en la parcial _form. Allí añadimos un nuevo div con un id representativo donde más rabia nos dé. Yo le llamo map_canvas por costumbre. también tendremos que insertar un botón para que el usuario verifique la geocodificación antes de continuar.

= form_for(@user) do |f|
  - if @user.errors.any?
    #errorExplanation
      %h2= "#{pluralize(@user.errors.count, 'error')} prohibited this user from being saved:"
      %ul
      - @user.errors.full_messages.each do |msg|
        %li= msg
  .field
    = f.label :nombre
    %br=f.text_field :nombre
  .field
    = f.label :direccion
    %br= f.text_field :direccion
  .field
    = f.label :provincia
    %br= f.text_field :provincia
  .field
    = f.label :pais
    %br= f.text_field :pais
  #map_canvas{:style=>"width: 400px; height: 400px;"}
  .field
    %input#geocodifica{:type => :button, :value=> 'Encontrar calle' }
  .field
    = f.label :lat
    %br= f.text_field :lat
  .field
    = f.label :lng
    %br= f.text_field :lng
  .actions
    = f.submit

Además hay que incluir la librería javascript de google. En el fichero de layout, incluid javascript_include_tag 'http://maps.google.com/maps/api/js?sensor=false' dentro de la cabecera (sección head) del documento, pero ANTES que la inclusión de los demás ficheros JS. Sino, cuando hagamos referencia a google.maps en nuestro código puede ser que nos diga que no encuentra esa referencia.
Como yo trabajo habitualmente con la librería jquery, también la incluyo. En este caso, he descargado la ultima versión de http://jquery.com/ con el nombre de jquery.js, y lo he incluido como otro fichero más, pero también antes de incluir application.js
Esto es todo lo necesario, ahora vamos a picar código javascript en el fichero public/javascript/application.js

var mapOptions = {zoom: 13,
                  center: new google.maps.LatLng(43.35564,-8.389435),
                  mapTypeId: google.maps.MapTypeId.ROADMAP};
var geocoder = new google.maps.Geocoder();

$(function initialize()
{
  var map = new google.maps.Map($("#map_canvas")[0],mapOptions);
  $("#geocodifica").click(function()
	{
		var address = $("#user_direccion").val() + ', '+$("#user_provincia").val()+', '+$("#user_pais").val();
		if (address)
		{
    	geocoder.geocode({'address':address,'partialmatch':true}, function(results,status)
			{
      	if (status == 'OK')
				{
					var editMarker = new google.maps.Marker( {position: results[0].geometry.location, map: map } );
					map.panTo(results[0].geometry.location);
					$("#user_lat").val(results[0].geometry.location.lat());
					$("#user_lng").val(results[0].geometry.location.lng());
				}
        else
				{
					alert('La geolocalizacion fallo debido a: '+status)
				}
			});
    }
 })
});

Explico un poco la parte referente a los mapas.

Crear el mapa es tan simple como hacer un new google.maps.map y pasarle el objeto del DOM que va a albergar dicho mapa, y un hash con las opciones del mapa. Este hash de opciones necesita al menos un centro, un nivel de zoom, y el tipo de mapa que queremos que nos muestre.
El objeto geocoder es el encargado de realizar la búsqueda. Recibe un objeto con las opciones (una tiene que ser la dirección a geocodificar). ‘Partialmatch’:true flexibiliza la búsqueda permitiendo a google buscar direcciones incompletas o “intuir” la geocodificación de direcciones mal escritas, como por ejemplo “Puarta del sol 1, Madrid, España”.
geocode tiene una función de callback que toma como parámetros un array de los resultados posibles (ordenador de más a menos probabilidad) y un status, que indica si la geocodificación tuvo éxito o no. Si fue exitosa, colocamos en el mapa map un marcador en la localización del resultado más probable. Además, centro el mapa en ese punto, como ayuda visual, y relleno los campos de latitud y longitud con sus valores.

Si el usuario considera correcta esa localización, al darle a nuevo usuario los campos de latitud y longitud ya contienen las coordenadas correctas geocodificadas. Nuestra aplicación solo lo almacena como almacenaría un campo normal, evitando carga de trabajo para nuestra servidor, y permitiendo al usuario detectar errores antes de guardar los datos.

Podríamos establecer más opciones, como por ejemplo permitir al usuario arrastrar el marcador para afinar su posición al 100%.

La geocodificación y google maps son dos de mis fetiches, así que habrá mas artículos que los toquen en próximos dias.

Hasta la próxima.

Anuncios

, , , ,

  1. Deja un comentario

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: