Ocultar InfoWindows en las capas creadas con Google Fusion Tables y Google Maps API

Las capas creadas con la API de Google Fusion Tables sobre los mapas de Google Maps creados con la API de este último servicio vienen con las ventanas de información integradas de manera tal que cada marcador desplegado sobre el mapa cuenta con su respectivo InfoWindows. Cada una de estas ventanas se llena con la información de la tabla de Google Fusion Tables, mostrando absolutamente todos los datos de todas las columnas.

Una práctica común es optar por los InfoBox en lugar de los InfoWindows con el objetivo de mostrar información de cada marcador debido a que estos ofrecen mayores opciones de personalización que las ventanas de información por defecto de Google Maps API. El problema se presenta cuando al terminal de implementar estos InfoBox nos encontramos con dos ventanas de información para cada marcador: una correspondiente al InfoWindows por defecto de la API y otro al InfoBox implementado.

Ocultar InfoWindows en las capas creadas con Google Fusion Tables y Google Maps API

Como se aprecia en la imagen tener las dos ventanas de información desplegadas (la del frente el InfoWindows y la del fondo el InfoBox) al hacer click en un marcador es absurdo y lo lógico es querer mostrar únicamente el InfoBox manualmente implementado por nosotros.

Por suerte desactivar los InfoWindows de la capa de Google Fusion Tables se lleva a cabo definiendo la propiedad suppressInfoWindows como true al momento de crear la capa, tal como se muestra en el siguiente pedazo de código:

var datos;
var layer;
var mapa;
var datos;
function inicializacion() {
	//Creo un mapa.
	var opciones_mapa = {zoom: 13,center: new google.maps.LatLng(-34.6074533313473, -58.37355852127075),mapTypeId: google.maps.MapTypeId.ROADMAP};
	map = new google.maps.Map(document.getElementById("mapa"), opciones_mapa);

	/*
	Creo la capa de Google Fusion Tables donde defino la propiedad
	suppressInfoWindows como true.
	*/
	layer = new google.maps.FusionTablesLayer({query: {select: 'coordenadas', from: '1-zmpFV_oI7OBiq3iEyHyze7QBiBDZzdrxby_TYM'},map: map, suppressInfoWindows: true});

	//Como he desactivado los InfoWindows tengo que crear los InfoBox.
	var opciones_infobox = {boxClass: 'datos', alignBottom: true, pixelOffset: new google.maps.Size(-50, -40), closeBoxURL: 'i/cruz.png', closeBoxMargin: '15px 15px 0px 0px'};
	datos = new InfoBox(opciones_infobox);

	/*
	Creo un evento asociado a la capa que se lleve a cabo cuando se
	registra un click sobre la misma de forma tal de poder desplegar
	los InfoBox de cada marcador.
	*/
	google.maps.event.addListener(layer, 'click', function(e) {
		/*
		Obtengo todos los datos que yo desee de la tabla de
		Google Fusion Tables para mostrarlos luego en la
		ventana de información (el InfoBox).
		*/
		var id = e.row['id'].value;
		var nombre = e.row['nombre'].value;
		var direccion = e.row['direccion'].value;
		var telefono = e.row['telefono'].value;
		var dias_habiles = e.row['dias_habiles'].value;
		var sabados = e.row['sabados'].value;
		var domingos = e.row['domingos'].value;

		var reportar = '<a onclick="window.open(this.href, this.target, \'width=500,height=500\'); return false;" href="reportar.php?id='+id+'" target="_blank">¿La información contiene errores?</a>';

		//Defino el contenido del InfoBox.
		datos.setContent('<div class="contenido"><h2>'+nombre+'</h2><p class="direccion">'+direccion+'</p><p class="telefono">'+telefono+'</p><ul><li><span>Lunes a Viernes:</span> '+dias_habiles+'</li><li><span>Sábados:</span> '+sabados+'</li><li><span>Domingos:</span> '+domingos+'</li></ul><p class="reportar">'+reportar+'</p></div>');
		
		/*
		Defino la posición del InfoBox sobre el mapa en base
		a las coordenadas del marcador en el cual se hace click.
		*/
		datos.setPosition(e.latLng);

		//Muestro el InfoBox.
		datos.open(map);
	});
}

No he montado una página de demostración para este código porque considero que queda claro con lo escrito y porque se trata de un tema simple. De igual forma en un proyecto personal titulado Misas en Buenos Aires hago uso de esta técnica y pueden remitirse al código de la página para más información (la imagen de este artículo proviene de dicho proyecto).

Algoritmo para calcular el CUIL o CUIT

El CUIL o CUIT que todo Argentino tiene no es confeccionado mediante algún algoritmo ultra secreto de la ANSES sino que se trata de un cálculo matemático utilizando el número de documento o número de sociedad asignado por la AFIP y otros números fijos dependiendo de ciertas condiciones.

Explicación del cálculo matemático

Para empezar hay que tener en cuenta que el CUIL o CUIT tiene el formato AB + 12345678 + C, donde AB es un prefijo relacionado con el tipo (hombre, mujer o sociedad), C un código de verificación y 12345678 no es más que el número de documento de la persona o número de sociedad de la empresa.

Determinar el prefijo implica saber si la persona es hombre, mujer o si se trata de una sociedad de tal forma que para los hombres AB es 20, para las mujeres 27 y para las sociedades 30. Más adelante nos damos cuenta que AB puede cambiar.

Conocer C requiere llevar a cabo unos cálculos un poco más enredados. Se empieza por multiplicar cada caracter de la cadena AB + 12345678 por los números 5, 4, 3, 2, 7, 6, 5, 4, 3, 2 respectivamente y sumar los resultados. Lo que necesitamos de este número es el resto obtenido al dividirlo por 11.

Finalmente se entra en una serie de evaluación de condiciones para determinar finalmente cuanto vale C y si AB se mantiene intacto o cambia:

  • Si el resto obtenido es 0 entonces C vale 0 y AB no cambia.
  • Si el resto es 1 entonces C es 9 para los hombres y 4 para las mujeres, mientras que AB cambia a 23 para ambos.
  • En caso de que el resto no sea 0 o 1, o que se trate de una sociedad, C es el resultado de restarle el resto al número 11, y AB no cambia.

Supongamos que un hombre cuyo documento es 12344321 quiere conocer su CUIL. Partimos determinando que AB es 20, luego multiplicamos la cadena 20 - 12344321 por los números que antes comentamos, sumamos todos estos resultados y obtenemos 102. El resto de dividir 102 por 11 es 3, así que no entramos a ninguna de las dos primeras condiciones sino que a la última.

Esta tercer condición nos dice que para obtener C tenemos que restarle a 11 el resto, es decir 11-3, lo cual nos da 8. El CUIL de esta persona imaginaria es 20 - 12344321 - 8.

Algoritmo en JavaScript

Conociendo el cálculo matemático que se lleva a cabo para determinar el CUIL o CUIT se puede programar un algoritmo que se encargue de este proceso en cualquier lenguaje. En mi caso decidí hacerlo en JavaScript y montar una página de ejemplo junto a un formulario para que lo puedan ver en acción.

function cuil_cuit(){
	//Defino el si se trata de un hombre, mujer o sociedad.
	var genero = "hombre";
	//Defino el número de documento o de sociedad.
	var documento = "12344321";

	/*
	Verifico que el documento tenga exactamente ocho números y que
	la cadena no contenga letras.
	*/
	if((documento.length!=8)||(isNaN(documento))){
		//Muestro un error en caso de no serlo.
		alert("El número de documento ingresado no es correcto.")
	} else {
		//Defino el valor del prefijo.
		if(genero=='hombre') {
			var AB = '20';
		} else if(genero=='mujer') {
			var AB = '27';
		} else {
			var AB = '30';
		}

		/*
		Los números (excepto los dos primeros) que le tengo que
		multiplicar a la cadena formada por el prefijo y por el
		número de documento los tengo almacenados en un arreglo.
		*/
		var multiplicadores = new Array('3', '2', '7','6', '5', '4', '3', '2');

		//Realizo las dos primeras multiplicaciones por separado.
		var calculo = ((parseInt(AB.charAt(0))*5)+(parseInt(AB.charAt(1))*4));
		/*
		Recorro el arreglo y el número de documento para
		realizar las multiplicaciones.
		*/
		for(var i=0;i<8;i++) {
			calculo += (parseInt(documento.charAt(i))*parseInt(multiplicadores[i]));
		}

		//Calculo el resto.
		var resto = (parseInt(calculo))%11;

		/*
		Llevo a cabo la evaluación de las tres condiciones para
		determinar el valor de C y conocer el valor definitivo de
		AB.
		*/
		if((genero!='sociedad')&&(resto<=1)){
			if(resto==0){
				var C = '0';
			} else {
				if(genero=='hombre'){
					var C = '9';
				} else {
					var C = '4';
				}
			}
			AB = '23';
		} else {
			 var C = 11-resto;
		}

		//Almaceno el CUIL o CUIT en una variable.
		var cuil_cuit = AB+"-"+documento+"-"+C;

		//Lo muestro en la ventana del navegador.
		alert(cuil_cuit);
	}
}

Ver demostración

Unas últimas consideraciones

Algunos números de CUIL comienzan con 24, algo no contemplado en este o ningún otro algoritmo que puedan encontrar en Internet. La razón de los números de CUIL con prefijo 24 es debido a una medida de la ANSES para evitar un duplicado en casos particulares con personas con números de documento que luego de todo el cálculo matemático resulten en el mismo resultado.

No hay forma de encontrar esta excepción a la regla puesto que se debería de contar con acceso a la base de datos de la propia ANSES. Para todos los demás el CUIL o CUIT obtenido debería de ser el correcto.

Screencast en Mac OS sin programas adicionales con QuickTime Player

Siempre es una sorpresa para mi encontrarme con la posibilidad de llevar a cabo acciones en Mac OS con las propias aplicaciones nativas del sistema operativo y sin recurrir a software de terceros. Bajo la necesidad de grabar lo que sucedía en mi pantalla me encontré con que es posible utilizar QuickTime Player.

El programa es sencillo, sin muchas opciones de configuración, quizás pensado particularmente para screencast caseros y vídeos de pocos minutos en los que simplemente se necesita mostrar algo de la pantalla sin recurrir a pesados software con opciones mucho más avanzadas. Básicamente podremos seleccionar el área a grabar (o toda la pantalla), la calidad del vídeo, y si queremos o no sumar audio utilizando el micrófono.

La última de las opciones corresponde a la posibilidad de resaltar los clicks con el puntero, algo ideal para la confección de guías y mejorar la forma de orientar al usuario en lo que tiene que hacer.

Screencast en Mac OS sin programas adicionales con QuickTime Player

Lo único que estaría muy bueno que sea incorporado y que por el momento no es posible, es la grabación del audio interno de la computadora, es decir el audio que proviene del propio sistema operativo y no que entra por el micrófono. Pero no deja de ser un detalle menor y quizás un capricho.

Finalizada la grabación obtendremos un archivo .mov que luego podremos editar con iMovie o cualquier otro software de edición de vídeo para agregarle efectos o realizar cualquier otro tipo de mejoras que creamos convenientes.

Convertir una página web en un archivo PSD separado en capas

Una de las prácticas más comunes del front-end development es recibir el diseño en, por suponer, formato PDS y a partir del mismo maquetar la página web en cuestión. Incluso hay empresas dedicadas a esta tarea específica, normalmente conocidas como aquellas que dan servicios de PSD to HTML a diseñadores gráficos sin conocimientos en programación.

Lo que me sorprende es la aplicación para OS X llamada Page Layers que hace exactamente lo inverso: a partir de una página web cualquiera genera un archivo PSD con el diseño. Pero esto sería irrelevante si no fuese porque el programa separa todos los elementos del sitio en cuestión en diferentes capas (layers).

Convertir una página web en un archivo PSD separado en capas

En base al archivo .psd creado a partir de la página de inicio de Twitter, que el sitio de Page Layers ofrece como demostración, se puede inferir que la aplicación funciona demasiado bien para ser cierto. Teniendo la oportunidad de probar el software lo sometí a varias pruebas y el resultado siempre es igual de excelente cualquiera sea el sitio que se le ponga adelante.

Uno se queda con la sensación de que un diseñador profesional se ha encargado de realizar el trabajo y no una aplicación de computadora. Basándose en la estructura del código de la página la aplicación logra separar en capas cada elemento, agrupados en inteligentes carpetas, pudiendo manipular las mismas a diestra y siniestra.

El programa es simple puesto que la única configuración que uno como usuario puede efectuar es definir el tamaño del navegador integrado para generar el .psd en base a dichas dimensiones. El proceso de conversión es prácticamente instantáneo.

A pesar de que cumpla lo que promete, Page Layers me genera preguntarme para qué necesitaría yo hacer esto, ¿en que contexto laboral necesitaría transformar cualquier página en un PSD separado en capas? En base a algunas opiniones de usuarios de la aplicación al parecer este software es útil para llevar a cabo rediseños en proyectos de los cuales no se cuenta con el diseño original.

Las metodologías de trabajo así como las condiciones particulares de un proyecto son tan, valga la redundancia, particulares a cada proyecto que a pesar de que yo no le encuentre en mi vida utilidad a esta aplicación a seguro muchos les agilizará o mejorará el trabajo que hagan.

El lado malo de toda esta historia es que, dejando de lado que esta disponible únicamente para usuarios de Mac OS X, la aplicación no es gratuita y no se ofrece ningún tipo de versión de prueba. La compra no deja de ser un riesgo, y a esto lo considero un error de parte de quienes crearon Page Layers, pero no queda más que conformarse con el .psd de ejemplo, las positivas opiniones de los usuarios y mi palabra, confiando en que el resto de los sitios que “procesemos” tengan el mismo excelente resultado final.

Jailbreak untethered para iPhone, iPad o iPod Touch con iOS 6.1 usando evasi0n

Por más que mi relación con el jailbreak haya terminado hace más de dos años y que por alguna que otra razón no lo necesito ni deseo como si lo hacía antes, me gusta escribir guías en referencia a este tema y ayudar a todo aquel “reincidente” o primerizo con ganas de desbloquear su iPhone, iPad o iPod Touch para luego aprovechar todas las aplicaciones de terceros que vienen de la mano de Cydia.

El jailbreak hoy en día es sencillo y simple gracias a que no hay que tener en cuenta tantas versiones, dispositivos compatibles, modelos, y no se cuantas cosas más que antes si eran un dolor de cabeza. Con el programa evasi0n podremos hacer el jailbreak a cualquier dispositivo con iOS desde 6.0 hasta 6.1 (y toda versión entremedio), ya sea un iPhone, iPad, iPad Mini, o iPod Touch en cualquiera de sus versiones, cualquiera sea su capacidad, independientemente de si soportan o no 3G o LTE. Simplemente a todos.

Antes de comenzar

Se recomienda antes de comenzar el proceso realizar una copia de seguridad del dispositivo mediante iTunes o iCloud, y actualizar a iOS 6.1 usando iTunes y no mediante OTA (aunque esto último es recomendación, no obligatoriedad).

Si tenemos activado el código de desbloqueo se aconseja deshacernos de el hasta terminado el proceso porque puede ocasionar inconvenientes. De la misma forma hay que deshabilitar las copias de seguridad encriptadas que realiza iTunes.

Y por último, antes de comenzar, necesitamos descargarnos evasi0n para Mac (versión 10.5 como mínimo), para Windows (XP como mínimo) o para Linux desde el propio sitio de evasi0n (no coloco enlace directo por si se producen actualizaciones en el programa).

Realizando el propio Jailbreak

Conectado el dispositivo a la computadora mediante el cable USB y estando iTunes cerrado ejecutamos evasi0n. Se nos dará una cálida bienvenida al programa y se nos reconocerá el dispositivo (en mi caso un iPhone 4S con iOS 6.1). Si el mismo es compatible podremos continuar el proceso simplemente presionando en Jailbreak.

Habrá que esperar no más de cinco minutos en los cuales tendremos que no tocar el iPhone y tratar de no tocar la computadora (ni hablar de abrir programas relacionados con el dispositivo como iTunes o Xcode). Pasado este tiempo necesitaremos intervenir cuando se nos lo solicite para ejecutar una nueva aplicación que aparecerá en nuestro dispositivo titulada Jailbreak.

Jailbreak untethered para iPhone, iPad o iPod Touch con iOS 6.1 usando evasi0n

Al ejecutarla una única vez la pantalla se volverá negra y volverá a la pantalla de Inicio (es cuestión de un segundo), y evasi0n terminará de trabajar en nuestro dispositivo (de nuevo a no tocar nada hasta que el mismo termine y reinicie).

Jailbreak untethered para iPhone, iPad o iPod Touch con iOS 6.1 usando evasi0n

Mientras tanto podemos ir cerrando evasi0n en nuestra computadora puesto que no lo necesitamos más.

Finalizado este más que corto proceso nos encontraremos con Cydia, signo de que nuestro dispositivo se encuentra con jailbreak y funcionando a la perfección.

Obtener las coordenadas de un punto en un mapa creado con la API de Google Maps

Si bien ya he escrito un artículo para obtener las coordenadas de un punto en Google Maps, el mismo se enfocaba al servicio propio de Google al cual podemos acceder en maps.google.com, pero debido a un comentario me di cuenta que me quedo pendiente la forma de obtener las coordenadas de un punto en un mapa creado por nosotros con la API de Google Maps.

“Supongamos que tenemos un mapa en una web y queremos que aparezca una marca en un punto del mapa cuando hacemos click ahí. ¿Como hacemos para capturar las coordenadas donde hemos hecho click y pasarselas a la función JavaScript que pinta la marca?” -Duque

Para darle solución a este planteo yo propongo el siguiente código que le asigna un evento al mapa que tengamos creado, y que se lleva a cabo cuando se hace click sobre alguna parte del mismo.

function inicializacion() {
     //Creo un nuevo mapa situado en Buenos Aires, Argentina, con 13 de Zoom y del tipo ROADMAP
     var mapa = new google.maps.Map(document.getElementById("mapa"),{center: new google.maps.LatLng(-34.60371794474704, -58.38158369064331),zoom: 13,mapTypeId: google.maps.MapTypeId.ROADMAP});

     //Creo un evento asociado a "mapa" cuando se hace "click" sobre el
     google.maps.event.addListener(mapa, "click", function(evento) {
     //Obtengo las coordenadas separadas
     var latitud = evento.latLng.lat();
     var longitud = evento.latLng.lng();

     //Puedo unirlas en una unica variable si asi lo prefiero
     var coordenadas = evento.latLng.lat() + ", " + evento.latLng.lng();

    //Las muestro con un popup
     alert(coordenadas);

     //Creo un marcador utilizando las coordenadas obtenidas y almacenadas por separado en "latitud" y "longitud"
     var coordenadas = new google.maps.LatLng(latitud, longitud); /* Debo crear un punto geografico utilizando google.maps.LatLng */
     var marcador = new google.maps.Marker({position: coordenadas,map: mapa, animation: google.maps.Animation.DROP, title:"Un marcador cualquiera"});
     }); //Fin del evento
} // Fin inicializacion()

A grandes rasgos lo que se hace es tomar la latitud y longitud del punto donde se ha hecho click y asignar estos valores a dos variables (latitud y longitud). A si mismo se combinan las dos en una única variable (coordenadas) sin ningún fin en particular más que mostrar las diferentes formas de manipular estos datos.

En el código también he considerado la creación de un marcador en base a las coordenadas obtenidas, es por esto que utilizo la clase google.maps.LatLng para crear un punto geográfico y luego si llevar a cabo la creación y posicionamiento del marcador.

Obtener las coordenadas de un punto en un mapa creado con la API de Google Maps

Ver demostración

Queda en la capacidad de cada uno adaptar mi código a las necesidades particulares de cada proyecto, pero los pasos a seguir son básicamente los mismos: se crea un evento que se dispara al hacer click en el mapa, se obtienen las coordenadas con la latitud y longitud separadas y se las asigna a una o diferentes variables. De ahí en adelante, como ya tenemos en nuestro poder las coordenadas, podemos hacer lo que queramos.

Eliminar archivos de forma permanente sin pasar por la papelera en Mac OS

En Microsoft Windows con Shift + Suprimir eliminamos un archivo de forma permanente sin que este pase por la Papelera de Reciclaje, demasiado simple como para que luego tengamos que darnos cuenta que en Mac OS dicho funcionamiento no se encuentra implementado de forma nativa (ni siquiera podemos eliminar archivos específicos dentro de la Papelera siendo la única solución vaciarla por completo).

Para contar con esta posibilidad en los equipos de Apple podemos recurrir al servicio independiente Delete Immediately compatible con Snow Leopard y versiones superiores (funcionando a la perfección desde mi iMac con Mountain Lion 10.8.2) que agregará la opción de eliminar cualquier archivo seleccionado desde el menú contextual que se muestra al hacer click derecho, incluso en aquellos ya ubicados dentro de la Papelera.

Si abusamos de esta funcionalidad podemos incluso crear un atajo del teclado para replicar el comportamiento de Microsoft Windows.

Eliminar archivos de forma permanente sin pasar por la papelera en Mac OS

Descargar Delete Immediately desde GitHub

Su instalación es tan simple como arrastrar el archivo .service a la carpeta /Library/Services, cerrar y volver a iniciar sesión si es que no se muestra la opción de inmediato.