tag:blogger.com,1999:blog-6230959840389481677.post-66651998472519929962008-04-20T04:51:00.000-07:002008-04-21T18:48:03.234-07:00Incorporando Google Maps en Application Express<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_fRmrOAuwnQ4/SAvD8wuVfEI/AAAAAAAAAEY/L0K6F5KcOD4/s1600-h/copa2.JPG"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp1.blogger.com/_fRmrOAuwnQ4/SAvD8wuVfEI/AAAAAAAAAEY/L0K6F5KcOD4/s320/copa2.JPG" alt="" id="BLOGGER_PHOTO_ID_5191458444113443906" border="0" /></a>Diversos artículos pueden encontrarse en Internet acerca de cómo implementar Google Maps en Oracle Application Express (APEX). Desafortunadamente, la mayoría son algo básicos y se limitan a cargar un mapa dentro de una región, no teniendo interacción con la base de datos.<br /><br />En esta oportunidad vamos a ver cómo lograr desplegar puntos dinámicamente en un mapa a partir de datos almacenados en una tabla. Únicamente se requieren conocimientos básicos de Application Express, PL/SQL y Javascript.<br /><br />Este artículo no pretende mostrar todas las funcionalidades de la API de Google Maps, sino resolver el problema puntual de programación en Oracle, luego dependerá de las habilidades Javascript del programador y de conocer a fondo las funcionalidades que brinda esta maravillosa API.<br /><br />Aclarado esto, comencemos, paso a paso:<br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">Paso 1: Tener APEX instalado.</span><br /><br />Lo primero es tener APEX instalado, ya que necesitaremos la URL o IP para el paso siguiente.<br />Si tienen duda si APEX está instalado en su base de datos, ver mi <a href="http://oraclenotepad.blogspot.com/2008/04/como-saber-si-aplication-express-apex.html" target="_blank">artículo anterior</a>.<br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">Paso 2: Solicitar una clave en Google Maps.</span><br /><br />Ir a la siguiente direccion <a href="http://code.google.com/apis/maps/signup.html" target="_blank">http://code.google.com/apis/maps/signup.html</a> para registrarnos y solicitar un código que necesitamos para utilizar el servicio. En el registro, se debe ingresar la URL donde será utilizado Google Maps.<br />Por ejemplo, si utilizamos el espacio gratuito <a href="http://apex.oracle.com/" target="_blank">Oracle Apex</a>, podemos ingresar la URL http://apex.oracle.com/pls/otn/. Si se está desarrollando localmente (en la propia máquina) puede registrarse la IP 127.0.0.1, pero cuando finalice el desarrollo habrá que solicitar una nueva clave con la URL de producción, ya que Google requiere que el sitio registrado sea de acceso público.<br />El código generado será referenciado desde de nuestro script.<br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">Paso 3: Manos a la obra con APEX!</span><br /><br />En nuestra nueva aplicación APEX, como primer paso debemos crear una página.<br /><br />Editar los atributos de la página y en el campo <span style="font-style: italic;" class="htmldbLabelOptional">Enfoque de Cursor</span> elegir el valor <span style="font-style: italic;">No enfocar Cursor.</span><br /><br />En la sección Cabecera HTML, incluir el siguiente script reemplazando nuestra clave:<br /><pre style="color: rgb(0, 153, 0);"><script src="http://maps.google.com/maps?file=api&v=2&key=<span style="color: rgb(51, 51, 255);">la_clave_de_google_maps</span>&hl=es"<br />type="text/javascript"></script><br /><script type="text/javascript"><br /><br />//<![CDATA[<br /><br />function load() {<br />if (GBrowserIsCompatible()) {<br />miMapa();<br />}<br />}<br /><br />//]]><br /></script></pre>En este javascript acabamos de definir la función load, la cual invoca a otra función miMapa que crearemos más adelante.<br /><br />En el campo <span style="font-style: italic;">Atributo de Cuerpo HTML de Página</span>, pegar lo siguiente:<pre style="color: rgb(0, 153, 0);">onload="load();" onunload="GUnload();"</pre><ul><li>Se puede observar cómo en el evento onload de la página, se invoca a la función load incluída en el cabezal HTML. </li></ul>Hecho esto, guardar los cambios efectuados en la página<br /><br />Ahora queda la parte interesante, ya que deberemos crear la función miMapa la cual ejecutará la carga del mapa y los puntos de referencia extraídos de la base de datos. Esta función será generada por un bloque anónimo PL/SQL el cual será ejecutado cada vez que se carga la página. <br />Para este ejemplo, se creó una sencilla tabla <span style="font-style: italic;">geopuntos</span> la cual contiene información sobre los puntos de referencia que queremos desplegar en nuestro mapa:<pre style="color: rgb(0, 153, 0);">id_punto NUMBER(10) NOT NULL<br />latitud NUMBER(18,15) NOT NULL<br />longitud NUMBER(18,15) NOT NULL<br />descripcion VARCHAR2(100)</pre><ul><li>La precisión de <span style="font-style: italic;">latitud</span> y <span style="font-style: italic;">longitud</span> es adecuada para almacenar coordenadas geográficas de Google Maps.<br /></li><li>Cada punto puede enriquecerse con valiosa información como pueden ser imagenes, archivos, links, íconos, etc.<br /></li><li>Se recomienda consultar la extensa documentación y tutoriales que brinda Google Maps en su sitio oficial.</li></ul>En el área <span style="font-style: italic;">Presentación de Página</span>, en la sección <span style="font-style: italic;">Procesos</span>, vamos a implementar nuestro bloque PL/SQL.<br>Crear un nuevo proceso de tipo <span style="font-style: italic;">PL/SQL</span>. En <span style="font-style: italic;">Atributos de Proceso</span>, ingresar un nombre cualquiera y elegir el valor <span style="font-style: italic;">En Carga, Antes de Cabecera</span>. Clickear siguiente, y en <span style="font-style: italic;">Proceso</span>, incluir el siguiente bloque:<pre style="color: rgb(0, 153, 0);">DECLARE<br /> CURSOR cr_puntos IS select * from puntosmapa;<br />BEGIN<br /> htp.p('<script type="text/javascript">');<br /> htp.p('//<![CDATA['); <br /> <br /> htp.p('function crearMarca(lat, long, descr) {');<br /> htp.p(' var point = new GLatLng(lat,long);');<br /> htp.p(' var opts = {title: descr};');<br /> htp.p(' var mark = new GMarker(point,opts);');<br /> htp.p(' GEvent.addListener(mark, "click", function() {<br /> mark.openInfoWindowHtml(''<div><B>'' + descr + ''</B><BR>Lat: '' + lat +<br /> ''<BR>Long: '' + long + ''</div>'');');<br /> htp.p(' });');<br /> htp.p('return mark;');<br /> htp.p('}'); <br /> <br /> htp.p('function miMapa() {'); <br /> htp.p('var map = new GMap2(document.getElementById("map"));');<br /> htp.p('map.addControl(new GLargeMapControl());');<br /> htp.p('map.addControl(new GMapTypeControl());');<br /> htp.p('map.addControl(new GOverviewMapControl());');<br /> htp.p('map.setCenter(new GLatLng(-22.915739,-43.22912), 11);');<br /> <br /> -- Recorro cursor e inserto los puntos<br /> FOR punto IN cr_puntos<br /> LOOP<br /> htp.p('var marker = crearMarca('||to_char(punto.latitud,'999.9999999999999999')||','<br /> ||to_char(punto.longitud,'999.9999999999999999')||',"'||punto.descripcion||'");'); <br /> htp.p('map.addOverlay(marker);');<br /> END LOOP;<br /> htp.p('}');<br /><br /> htp.p('//]]>');<br /> htp.p('</script>');<br />END;</pre>Este es el punto neurálgico de la aplicación: en este bloque PL/SQL resolvemos la consulta a la base de datos, la creación del mapa y la publicación de los puntos de referencia extraídos. Notar el uso de la función PL/SQL <span style="font-weight: bold;">htp.p()</span>. Así como DBMS_OUTPUT.PUT_LINE envia caracteres a la salida en pantalla, la función htp.p envía cadenas de caracteres al browser, y esto precisamente lo que necesitamos ya que queremos construir el Javascript a ser ejecutado en la carga de la página.<br /><br />Puede apreciarse la sencillez de esta implementación, en pocas líneas crea un mapa, lo centra y carga los controles básicos de zoom. La particularidad en este caso es el FOR LOOP, el cual recorre un cursor definido sobre la tabla, y en cada iteración define una marca "publicando" Javascript en tiempo de ejecución. Cada referencia tiene un toolTip cuando se pasa el mouse por encima y un globo informativo que se abre al clickear sobre la marca.<br /><br />Y eso es todo, tras guardar el proceso (dejar el resto de los valores por defecto), hemos concluído nuestra aplicación y ya está lista para ser explorada.<br /><br />Las posibilidades son muchísimas, y cuanto más se profundice sobre la documentación, mejores funcionalidades podremos lograr en APEX.<br><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">Un ejemplo implementado</span><pre style="color: rgb(0, 153, 0);"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_fRmrOAuwnQ4/SAu79QuVfBI/AAAAAAAAAEA/m61b7IqCx24/s1600-h/gmapsdemo.JPG"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp3.blogger.com/_fRmrOAuwnQ4/SAu79QuVfBI/AAAAAAAAAEA/m61b7IqCx24/s320/gmapsdemo.JPG" alt="" id="BLOGGER_PHOTO_ID_5191449656610356242" border="0" /></a></pre>Hice una página de demostración para que puedan ver que realmente funciona. En mi tabla de datos tengo almacenados puntos turísticos de Río de Janeiro, ciudad donde vivo actualmente :)<br /><br />Para saber las coordenadas geográficas de un punto en la tierra, podemos utilizar por ejemplo la página <a href="http://itouchmap.com/latlong.html" target="_blank">Geocoder</a>.<br /><br />Hay mucha documentación y ejemplos disponibles sobre Google Maps y realmente es fácil comenzar a obtener resultados sorprendentes.<br /><br />Finalmente le agradezco a Emilio Le Mener por su ayuda en Javascript.<br /><br />Espero que este tutorial haya sido útil y puedan comenzar a implementar sin problemas con APEX y Google Maps.<br /><div style="text-align: center;"><br /><img id="BLOGGER_PHOTO_ID_5175489526410503874" style="cursor: pointer;" alt="" src="http://bp1.blogger.com/_fRmrOAuwnQ4/R9MITahz5sI/AAAAAAAAADA/L9NY7wTm94I/s320/execute.jpg" border="0" /> <a href="http://apex.oracle.com/pls/otn/f?p=45998:1:4251456126624924:::::" target="_blank">Probar la Demo</a><br /></div><div style="text-align: center;"></div><span style="font-weight: bold;">Ver también:</span><br /><a href="http://code.google.com/apis/maps/index.html" target="_blank">Google Maps API</a><br /><a href="http://doug.ricket.com/gdd2007/" target="_blank">Presentación Google Developer Day 2007</a>lferhttp://www.blogger.com/profile/00618392085702183279noreply@blogger.com