<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Alex Franco &#8211; Alejandro Franco</title>
	<atom:link href="https://jafrancov.com/author/jafrancov/feed/" rel="self" type="application/rss+xml" />
	<link>https://jafrancov.com</link>
	<description>Blog de Alejandro Franco, aquí podrás encontrar temas de tecnología, desarrollo web y móvil, Python, Django, Mongo, DBs y... otros temas más</description>
	<lastBuildDate>Tue, 11 Jan 2022 18:38:25 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
<site xmlns="com-wordpress:feed-additions:1">14205669</site>	<item>
		<title>Enviar correo personalizado automáticamente cuando respondan un Formulario de Google</title>
		<link>https://jafrancov.com/2022/01/enviar-correo-personalizado-automaticamente-cuando-respondan-un-formulario-de-google/</link>
					<comments>https://jafrancov.com/2022/01/enviar-correo-personalizado-automaticamente-cuando-respondan-un-formulario-de-google/#comments</comments>
		
		<dc:creator><![CDATA[Alex Franco]]></dc:creator>
		<pubDate>Tue, 11 Jan 2022 18:36:52 +0000</pubDate>
				<category><![CDATA[Codigo]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Apps Script]]></category>
		<category><![CDATA[Formularios]]></category>
		<category><![CDATA[GMail]]></category>
		<category><![CDATA[Google Apps Script]]></category>
		<category><![CDATA[Google Drive]]></category>
		<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jafrancov.com/?p=2628</guid>

					<description><![CDATA[Ejemplo de cómo automatizar una respuesta cuando responden un formulario de Google, incluyendo la generación de un folio o número secuencial personalizado, agregar imágenes al correo de respuesta, y más. Código https://github.com/jafrancov/Google-Apps-Scripts/blob/master/forms/notifyOnFormSubmit.js Uno de tantos editores WYSIWYG de HTML https://html5-editor.net/ Límite de envíos diarios https://developers.google.com/apps-script/guides/services/quotas Enjoy!]]></description>
										<content:encoded><![CDATA[
<p>Ejemplo de cómo automatizar una respuesta cuando responden un formulario de Google, incluyendo la generación de un folio o número secuencial personalizado, agregar imágenes al correo de respuesta, y más. </p>



<ul class="wp-block-list"><li>Código https://github.com/jafrancov/Google-Apps-Scripts/blob/master/forms/notifyOnFormSubmit.js </li><li>Uno de tantos editores WYSIWYG de HTML https://html5-editor.net/ </li><li>Límite de envíos diarios https://developers.google.com/apps-script/guides/services/quotas</li></ul>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe class="youtube-player" width="900" height="507" src="https://www.youtube.com/embed/SONKbAv9SLw?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-MX&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe>
</div></figure>



<p><em>Enjoy!</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jafrancov.com/2022/01/enviar-correo-personalizado-automaticamente-cuando-respondan-un-formulario-de-google/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2628</post-id>	</item>
		<item>
		<title>Django + AllAuth + Google OAuth 2.0</title>
		<link>https://jafrancov.com/2021/01/django-allauth-google-oauth-2-0/</link>
					<comments>https://jafrancov.com/2021/01/django-allauth-google-oauth-2-0/#respond</comments>
		
		<dc:creator><![CDATA[Alex Franco]]></dc:creator>
		<pubDate>Sat, 09 Jan 2021 18:15:49 +0000</pubDate>
				<category><![CDATA[Codigo]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[AllAuth]]></category>
		<category><![CDATA[Bootstrap]]></category>
		<category><![CDATA[CrispyForms]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Google OAuth]]></category>
		<category><![CDATA[OAuth 2.0]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://jafrancov.com/?p=2621</guid>

					<description><![CDATA[Un ejercicio para demostrar la integración de Django AllAuth para el control de cuentas de usuario. En resumen: Configuración básica de entorno virtual y Django. Instalación y configuración de AllAuth. Integración de Bootstrap y Crispy Forms. Configuración y autenticación con Google Oauth 2.0 Enjoy!]]></description>
										<content:encoded><![CDATA[
<p>Un ejercicio para demostrar la integración de Django AllAuth para el control de cuentas de usuario. </p>



<p>En resumen:</p>



<ul class="wp-block-list"><li>Configuración básica de entorno virtual y Django.</li><li>Instalación y configuración de AllAuth.</li><li>Integración de Bootstrap y Crispy Forms.</li><li>Configuración y autenticación con Google Oauth 2.0</li></ul>



<figure class="wp-block-embed is-type-rich is-provider-gestor-del-servicio wp-block-embed-gestor-del-servicio wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe class="youtube-player" width="900" height="507" src="https://www.youtube.com/embed/jEJFK6jF5CE?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-MX&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe>
</div></figure>



<p><em>Enjoy!</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jafrancov.com/2021/01/django-allauth-google-oauth-2-0/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2621</post-id>	</item>
		<item>
		<title>Agregar número consecutivo y enviar correo al contestar Formulario de Google Drive</title>
		<link>https://jafrancov.com/2016/01/consecutivo-email-form-google-drive/</link>
					<comments>https://jafrancov.com/2016/01/consecutivo-email-form-google-drive/#comments</comments>
		
		<dc:creator><![CDATA[Alex Franco]]></dc:creator>
		<pubDate>Mon, 25 Jan 2016 17:28:10 +0000</pubDate>
				<category><![CDATA[Codigo]]></category>
		<category><![CDATA[Featured Articles]]></category>
		<category><![CDATA[Videos]]></category>
		<category><![CDATA[Consecutivo]]></category>
		<category><![CDATA[Forms]]></category>
		<category><![CDATA[Formularios]]></category>
		<category><![CDATA[Google Drive]]></category>
		<category><![CDATA[Sequence number]]></category>
		<guid isPermaLink="false">http://jafrancov.com/?p=2392</guid>

					<description><![CDATA[En este ejemplo agregaremos un número consecutivo (secuencial, auto-incremental) a cada registro que ingrese a un formulario de Google Drive, además tomamos el ejemplo de un video anterior de mandar un correo electrónico para mostrar una posible aplicación de estas tareas. Código: Github @jafrancov]]></description>
										<content:encoded><![CDATA[<p>En este ejemplo agregaremos un número consecutivo (secuencial, auto-incremental) a cada registro que ingrese a un formulario de Google Drive, además tomamos el ejemplo de un video anterior de mandar un correo electrónico para mostrar una posible aplicación de estas tareas.</p>
<p><iframe class="youtube-player" width="900" height="507" src="https://www.youtube.com/embed/woxWjLrNO-4?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-MX&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
<p>Código: <a href="https://github.com/jafrancov/Google-Apps-Scripts/blob/master/forms/sequenceOnFormSubmit.js" target="_blank">Github @jafrancov</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jafrancov.com/2016/01/consecutivo-email-form-google-drive/feed/</wfw:commentRss>
			<slash:comments>41</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2392</post-id>	</item>
		<item>
		<title>Servir o publicar imágenes con Django y MongoDB (GridFS)</title>
		<link>https://jafrancov.com/2014/09/servir-publicar-imagenes-django-mongodb-gridfs/</link>
					<comments>https://jafrancov.com/2014/09/servir-publicar-imagenes-django-mongodb-gridfs/#respond</comments>
		
		<dc:creator><![CDATA[Alex Franco]]></dc:creator>
		<pubDate>Tue, 23 Sep 2014 17:13:46 +0000</pubDate>
				<category><![CDATA[Codigo]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[GridFS]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[mongoengine]]></category>
		<category><![CDATA[pymongo]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">http://jafrancov.com/?p=2359</guid>

					<description><![CDATA[Mezclar Django y MongoDB es una tarea interesante, con los retos que implica ya que Django por default no tiene una integración con MongoDB como Base de Datos, sin embargo se han hecho esfuerzos por unirlos y hacerlos trabajar sacando las ventajas de ambos. Uno de los retos con los que me topé es usar ... <a title="Servir o publicar imágenes con Django y MongoDB (GridFS)" class="read-more" href="https://jafrancov.com/2014/09/servir-publicar-imagenes-django-mongodb-gridfs/" aria-label="Leer más sobre Servir o publicar imágenes con Django y MongoDB (GridFS)">Leer más</a>]]></description>
										<content:encoded><![CDATA[<p>Mezclar Django y MongoDB es una tarea interesante, con los retos que implica ya que Django por default no tiene una integración con MongoDB como Base de Datos, sin embargo se han hecho esfuerzos por unirlos y hacerlos trabajar sacando las ventajas de ambos.</p>
<p>Uno de los retos con los que me topé es usar GridFS que podemos entenderlo así:</p>
<blockquote><p>MongoDB puede ser utilizado con un sistema de archivos, tomando la ventaja de la capacidad que tiene MongoDB para el balanceo de carga y la replicación de datos utilizando múltiples servidores para el almacenamiento de archivos. Esta función (que es llamada <strong>GridFS</strong> ) está incluida en los drivers de MongoDB y disponible para los lenguajes de programación que soporta MongoDB. Esta base de datos expone funciones para la manipulación de archivos y contenido a los desarrolladores. En un sistema con múltiple servidores, los archivos pueden ser distribuidos y copiados entre los mismos varias veces y de una forma transparente, de esta forma se crea un sistema eficiente que maneja fallos y balanceo de carga.</p></blockquote>
<p>Bien, en resumen, es un sistema de archivos de MongoDB.</p>
<p>Mi problema era publicar las imágenes dado que no las almacena en una carpeta pública por así decirlo, así que había que buscar la solución vía programación. Antes de seguir, los paquetes que estoy usando son los siguientes:</p>
<ul>
<li>Django</li>
<li>MongoDB</li>
<li>mongoengine</li>
<li><a href="https://github.com/jschrewe/django-mongodbforms">django-mongodbforms</a></li>
<li>PIL</li>
</ul>
<p>Para el caso usé un modelo bastante sencillo, digamos que mi aplicación es un Blog y mi modelo es de un Post</p>
<pre class="brush: python; title: ; notranslate">
from mongoengine import *
from mongodbforms import DocumentForm


class Post(Document):
    title = StringField(max_length=160, required=True)
    body = StringField(required=True)
    image = ImageField(size=(800, 600, True), thumbnail_size=(150, 112, True))


class PostForm(DocumentForm):
    class Meta:
        document = Post
</pre>
<p>Hay 2 maneras de realizar la tarea:</p>
<ol>
<li>Sin thumbnail (miniatura), donde es 100% django.</li>
<li>Con thumbnail, donde tendremos que recurrir a pymongo + django</li>
</ol>
<p>La primera es muy sencilla, si tu aplicación no requiere de miniaturas, esta es la mejor opción, simplemente requieres conocer el ID de tu imagen:</p>
<pre class="brush: python; title: ; notranslate">
''' blog/views.py '''
def view_post(request, id):
    post = get_document_or_404(Post, pk=id)
    # img_id temporal para mandar llamar la imagen
    # Si no contiene imagen el post, no muestra nada
    try:
        post.img_id = post.image._id
    except AttributeError:
        post.img_id = False
    return render_to_response('post.html', {'post': post})


def display_image(request, id):
    image = get_document_or_404(Post, image=ObjectId(id)).image
    return HttpResponse(image.read(), content_type=image.contentType)


''' blog/urls.py '''
# ...
                       url(r'^post/(?P&lt;id&gt;\w+)/$', 'view_post'),
                       url(r'^media/(?P&lt;id&gt;\w+)$', 'display_image'),
# ...


''' blog/templates/post.html '''
&lt;p&gt;&lt;a href=&quot;/blog/&quot;&gt;View all posts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;h2&gt;{{ post.title }}&lt;/h2&gt;&lt;/p&gt;
&lt;p&gt;{{ post.body }}&lt;/p&gt;
{% if post.img_id %}
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/blog/media/{{ post.img_id }}&quot;&gt;&lt;/p&gt;
{% endif %}
</pre>
<p>Si por alguna razón requieres el uso de las miniaturas, esta es la receta de cocina para obtener la imagen regular o la miniatura, esto es debido a que directamente con el ORM de Django con mongoengine no hay manera de hacer referencia a la miniatura:</p>
<pre class="brush: python; title: ; notranslate">
''' blog/views.py '''
def view_post_th(request, id):
    post = get_document_or_404(Post, pk=id)
    # img_id temporal para mandar llamar la imagen
    # Si no contiene imagen el post, no muestra nada
    try:
        post.img_id = post.image._id
    except AttributeError:
        post.img_id = False
    try:
        post.thumbnail_id = post.image.thumbnail_id
    except AttributeError:
        post.thumbnail_id = False
    return render_to_response('post2.html', {'post': post})


def display_image_m2(request, id):
    # Conexión adicional al sistema de archivos de MongoDB
    mongo_con = Connection()
    # Si tu campo en el modelo es ImageField, la collección es 'images'
    grid_fs = gridfs.GridFS(mongo_con.servemedia, collection='images')
    if not grid_fs.exists(ObjectId(id)):
        raise Exception(&quot;Mongo file does not exist! {0}&quot;.format(ObjectId(id)))
    image = grid_fs.get(ObjectId(id))
    try:
        # Con esta validación sabemos si es miniatura o imagen original,
        # el thumbnail por default se guarda sin el contentType
        content_type = image.contentType
    except AttributeError:
        # Con esto buscamos la imagen original para obtener el contentType del thumbnail
        for grid_out in grid_fs.find({'thumbnail_id': ObjectId(id)}).limit(1):
            content_type = grid_out.contentType
    return HttpResponse(image.read(), content_type=content_type)


''' blog/urls.py '''
# ...
                       url(r'^post2/(?P&lt;id&gt;\w+)/$', 'view_post_th'),
                       url(r'^media2/(?P&lt;id&gt;\w+)$', 'display_image_m2'),
# ...


''' blog/templates/post2.html '''
&lt;p&gt;&lt;a href=&quot;/blog/&quot;&gt;View all posts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;h2&gt;{{ post.title }}&lt;/h2&gt;&lt;/p&gt;
&lt;p&gt;{{ post.body }}&lt;/p&gt;
{% if post.thumbnail_id %}
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/blog/media2/{{ post.thumbnail_id }}&quot;&gt;&lt;/p&gt;
{% endif %}
{% if post.img_id %}
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/blog/media2/{{ post.img_id }}&quot;&gt;&lt;/p&gt;
{% endif %}
</pre>
<p>El código completo puedes encontrarlo en mi GitHub  <a href="https://github.com/jafrancov/Serve-Media-Django-MongoDB-GridFS">https://github.com/jafrancov/Serve-Media-Django-MongoDB-GridFS</a> espero les sirva y sea de su agrado, cualquier duda, deja tu comentario.</p>
<p style="text-align: right;"><em>Enjoy!</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jafrancov.com/2014/09/servir-publicar-imagenes-django-mongodb-gridfs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2359</post-id>	</item>
		<item>
		<title>Combinación de Correspondencia con Google Drive (Docs + Hoja de Cálculo + GMail)</title>
		<link>https://jafrancov.com/2014/04/doc-merge-google-drive-docs-spreadsheet-gmail/</link>
					<comments>https://jafrancov.com/2014/04/doc-merge-google-drive-docs-spreadsheet-gmail/#respond</comments>
		
		<dc:creator><![CDATA[Alex Franco]]></dc:creator>
		<pubDate>Tue, 08 Apr 2014 16:13:29 +0000</pubDate>
				<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[BD]]></category>
		<category><![CDATA[Docs]]></category>
		<category><![CDATA[Document Merge]]></category>
		<category><![CDATA[featured]]></category>
		<category><![CDATA[GMail]]></category>
		<category><![CDATA[Google Drive]]></category>
		<category><![CDATA[Hojas de Cálculo]]></category>
		<category><![CDATA[Spreadsheets]]></category>
		<guid isPermaLink="false">http://jafrancov.com/?p=2338</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[]]></content:encoded>
					
					<wfw:commentRss>https://jafrancov.com/2014/04/doc-merge-google-drive-docs-spreadsheet-gmail/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2338</post-id>	</item>
		<item>
		<title>Enviar correo después de contestar Formulario de Google Drive automáticamente</title>
		<link>https://jafrancov.com/2013/11/enviar-correo-al-contestar-formulario-google-drive/</link>
					<comments>https://jafrancov.com/2013/11/enviar-correo-al-contestar-formulario-google-drive/#comments</comments>
		
		<dc:creator><![CDATA[Alex Franco]]></dc:creator>
		<pubDate>Fri, 08 Nov 2013 13:06:38 +0000</pubDate>
				<category><![CDATA[Featured Articles]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[Formularios]]></category>
		<category><![CDATA[GMail]]></category>
		<category><![CDATA[Google Drive]]></category>
		<category><![CDATA[Scripts]]></category>
		<guid isPermaLink="false">http://jafrancov.com/?p=2313</guid>

					<description><![CDATA[¿Alguna vez han tenido la inquietud que cuando responden una encuesta o un examen en línea les envíe un correo con sus respuestas, o si crean un formulario de registro le envíe a cada inscrito un correo con el resumen de su evento o similar? La respuesta siempre caía en &#8220;hay que hacer un sistema ... <a title="Enviar correo después de contestar Formulario de Google Drive automáticamente" class="read-more" href="https://jafrancov.com/2013/11/enviar-correo-al-contestar-formulario-google-drive/" aria-label="Leer más sobre Enviar correo después de contestar Formulario de Google Drive automáticamente">Leer más</a>]]></description>
										<content:encoded><![CDATA[<p>¿Alguna vez han tenido la inquietud que cuando responden una encuesta o un examen en línea les envíe un correo con sus respuestas, o si crean un formulario de registro le envíe a cada inscrito un correo con el resumen de su evento o similar?</p>
<p>La respuesta siempre caía en &#8220;hay que hacer un sistema que nos haga eso&#8221;, pues ahora pueden ahorrarse unos cuántos pesos y un tiempo considerable, les comparto un tutorial que realicé donde al momento en que se envía un formulario hecho con Google Drive, además de que tenemos un registro, le envía un correo al usuario que ha completado el formulario con un resumen de sus respuestas. Estas son las bases, si quieres hacer algo más complejo, ya dependerá de tu imaginación.</p>
<p style="text-align: center;"><iframe loading="lazy" src="//www.youtube.com/embed/w6o0Dj3EmfE" width="480" height="360" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p>El código pueden encontrarlo en <a href="https://github.com/jafrancov/Google-Apps-Scripts/blob/master/forms/emailOnFormSubmit.js" target="_blank">este enlace</a>.</p>
<p style="text-align: right;"><em>Enjoy!</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jafrancov.com/2013/11/enviar-correo-al-contestar-formulario-google-drive/feed/</wfw:commentRss>
			<slash:comments>45</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2313</post-id>	</item>
		<item>
		<title>Combinar Correspondencia con Google Drive y GMail</title>
		<link>https://jafrancov.com/2013/11/combinar-correspondencia-google-drive-gmail/</link>
					<comments>https://jafrancov.com/2013/11/combinar-correspondencia-google-drive-gmail/#comments</comments>
		
		<dc:creator><![CDATA[Alex Franco]]></dc:creator>
		<pubDate>Thu, 07 Nov 2013 16:28:57 +0000</pubDate>
				<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[GMail]]></category>
		<category><![CDATA[Google Drive]]></category>
		<category><![CDATA[Spreadsheets]]></category>
		<guid isPermaLink="false">http://jafrancov.com/?p=2307</guid>

					<description><![CDATA[Durante los últimos meses he estado usando Google Drive como mi suite de Office principal, pero muchos a quienes les recomendaba usarlo tenían casi siempre la misma duda&#8230; &#8220;¿se puede hacer combinación de correspondencia?&#8220;, la respuesta es SI. Aquí les dejo un pequeño tutorial que hice sobre cómo hacer una combinación de correspondencia con Google ... <a title="Combinar Correspondencia con Google Drive y GMail" class="read-more" href="https://jafrancov.com/2013/11/combinar-correspondencia-google-drive-gmail/" aria-label="Leer más sobre Combinar Correspondencia con Google Drive y GMail">Leer más</a>]]></description>
										<content:encoded><![CDATA[<p>Durante los últimos meses he estado usando Google Drive como mi suite de Office principal, pero muchos a quienes les recomendaba usarlo tenían casi siempre la misma duda&#8230; &#8220;<strong>¿se puede hacer combinación de correspondencia?</strong>&#8220;, la respuesta es <strong>SI</strong>.</p>
<p>Aquí les dejo un pequeño tutorial que hice sobre cómo hacer una combinación de correspondencia con Google Drive, espero les sirva bastante.</p>
<p style="text-align: center;"><iframe loading="lazy" src="//www.youtube.com/embed/4pynVPcmD8M" height="360" width="480" allowfullscreen="" frameborder="0"></iframe></p>
<p style="text-align: right;">Enjoy!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jafrancov.com/2013/11/combinar-correspondencia-google-drive-gmail/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2307</post-id>	</item>
		<item>
		<title>Geocode Inverso: Buscar direcciones a partir de Coordenadas con GMaps API v3</title>
		<link>https://jafrancov.com/2012/10/reverse-geocode/</link>
					<comments>https://jafrancov.com/2012/10/reverse-geocode/#comments</comments>
		
		<dc:creator><![CDATA[Alex Franco]]></dc:creator>
		<pubDate>Tue, 30 Oct 2012 22:46:03 +0000</pubDate>
				<category><![CDATA[Codigo]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Direcciones]]></category>
		<category><![CDATA[Geocode]]></category>
		<category><![CDATA[Geocoding]]></category>
		<category><![CDATA[GMaps]]></category>
		<category><![CDATA[Maps]]></category>
		<guid isPermaLink="false">http://jafrancov.com/?p=2190</guid>

					<description><![CDATA[Si no tienes mucha experiencia o tienes dudas con respecto a algo que usemos en este post, puedes consultar los demás ejemplos que se han realizado anteriormente aquí. En un post anterior, vimos cómo hacer un Geocode Simple, donde obteníamos las coordenadas a partir de una dirección dada, es decir, podríamos poner cualquier combinación de calles, ... <a title="Geocode Inverso: Buscar direcciones a partir de Coordenadas con GMaps API v3" class="read-more" href="https://jafrancov.com/2012/10/reverse-geocode/" aria-label="Leer más sobre Geocode Inverso: Buscar direcciones a partir de Coordenadas con GMaps API v3">Leer más</a>]]></description>
										<content:encoded><![CDATA[<p>Si no tienes mucha experiencia o tienes dudas con respecto a algo que usemos en este post,<a href="http://jafrancov.com/tag/gmaps"> puedes consultar los demás ejemplos que se han realizado anteriormente aquí</a>.</p>
<p>En un post anterior, vimos cómo hacer un <a title="Geocode Simple: Buscar direcciones (coordenadas a partir de direcciones) con GMaps API v3" href="http://jafrancov.com/2011/06/geocode-gmaps-api-v3/">Geocode Simple</a>, donde obteníamos las coordenadas a partir de una dirección dada, es decir, podríamos poner cualquier combinación de calles, colonias, ciudad, etc. y obtener las coordenadas de esa dirección para colocarlas en un mapa. En este caso es al contrario,<strong> buscar direcciones (de acuerdo a la base de datos de Google) a partir de coordenadas</strong>.</p>
<p>Lo que haremos se resume en: escribir coordenadas (latitud, Longitud), verificar si existe, si existe, colocar un marcador, centrar y dar zoom en el mapa en la región de la dirección obtenida, si no existe la dirección arrojar un error diciendo que no existe.</p>
<p><a href="http://gmaps.alexfranco.mx/reverse-geocode"><img loading="lazy" decoding="async" class="aligncenter" title="Ver Demo Geocoding" src="http://sites.google.com/site/jafrancov/stuff/ver-demo.png" alt="Ver Demo Geocoding" width="140" height="57" /></a></p>
<p>Al igual que el ejemplo anterior, es necesario crear un objeto Geocoder, que nos permitirá hacer la interpretación de lo que intentemos buscar.</p>
<pre class="brush: jscript; title: ; notranslate">var geocoder = new google.maps.Geocoder();</pre>
<p>El objeto que se obtiene de respuesta es un JSON, donde lo manejaríamos como regularmente se hace en javascript, el resultado es algo como esto:</p>
<pre class="brush: jscript; title: ; notranslate">
{
  &quot;status&quot;: &quot;OK&quot;,
  &quot;results&quot;: &#x5B; {
    &quot;types&quot;: &#x5B; &quot;street_address&quot; ],
    &quot;formatted_address&quot;: &quot;1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA&quot;,
    &quot;address_components&quot;: &#x5B; {
      &quot;long_name&quot;: &quot;1600&quot;,
      &quot;short_name&quot;: &quot;1600&quot;,
      &quot;types&quot;: &#x5B; &quot;street_number&quot; ]
    }, {
      &quot;long_name&quot;: &quot;Amphitheatre Pkwy&quot;,
      &quot;short_name&quot;: &quot;Amphitheatre Pkwy&quot;,
      &quot;types&quot;: &#x5B; &quot;route&quot; ]
    }, {
      &quot;long_name&quot;: &quot;Mountain View&quot;,
      &quot;short_name&quot;: &quot;Mountain View&quot;,
      &quot;types&quot;: &#x5B; &quot;locality&quot;, &quot;political&quot; ]
    }, {
      &quot;long_name&quot;: &quot;California&quot;,
      &quot;short_name&quot;: &quot;CA&quot;,
      &quot;types&quot;: &#x5B; &quot;administrative_area_level_1&quot;, &quot;political&quot; ]
    }, {
      &quot;long_name&quot;: &quot;United States&quot;,
      &quot;short_name&quot;: &quot;US&quot;,
      &quot;types&quot;: &#x5B; &quot;country&quot;, &quot;political&quot; ]
    }, {
      &quot;long_name&quot;: &quot;94043&quot;,
      &quot;short_name&quot;: &quot;94043&quot;,
      &quot;types&quot;: &#x5B; &quot;postal_code&quot; ]
    } ],
    &quot;geometry&quot;: {
      &quot;location&quot;: {
        &quot;lat&quot;: 37.4219720,
        &quot;lng&quot;: -122.0841430
      },
      &quot;location_type&quot;: &quot;ROOFTOP&quot;,
      &quot;viewport&quot;: {
        &quot;southwest&quot;: {
          &quot;lat&quot;: 37.4188244,
          &quot;lng&quot;: -122.0872906
        },
        &quot;northeast&quot;: {
          &quot;lat&quot;: 37.4251196,
          &quot;lng&quot;: -122.0809954
        }
      }
    }
  } ]
}
</pre>
<p>Lo único que nos faltaría es el código para validar, interpretar y dibujar. Para esto, hay 3 cosas importantes que debemos tomar en cuenta del JSON que tenemos de respuesta:</p>
<ul>
<li><em>status</em>: contiene la respuesta del estado de la petición, si fue satisfactoria o si hubo algún error y que tipo de error.</li>
<li><em>geometry.location</em>: la ubicación de la dirección solicitada.</li>
<li><em>geometry.viewport</em>: los límites recomendados para ajustar el zoom del mapa, haciendo un cuadrante con las esquinas Noreste (superior derecha) y Suroeste (inferior izquierda).</li>
</ul>
<p>Con esto en presente, la función siguiente nos mostrará solamente el primer resultado obtenido, quedando así :</p>
<pre class="brush: jscript; title: ; notranslate">
function codeLatLng() {
   var input = $('#latlng').val();
   var latlngStr = input.split(',', 2);
   var lat = parseFloat(latlngStr&#x5B;0]);
   var lng = parseFloat(latlngStr&#x5B;1]);
   var latlng = new google.maps.LatLng(lat, lng);
   geocoder.geocode({'latLng': latlng}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
         if (results&#x5B;0]) {
            map.fitBounds(results&#x5B;0].geometry.viewport);
            marker.setMap(map);
            marker.setPosition(latlng);
            $('#address').text(results&#x5B;0].formatted_address);
            infowindow.setContent(results&#x5B;0].formatted_address);
            infowindow.open(map, marker);
            google.maps.event.addListener(marker, 'click', function(){
               infowindow.setContent(results&#x5B;0].formatted_address);
               infowindow.open(map, marker);
            });
         } else {
            alert('No results found');
         }
      } else {
         alert('Geocoder failed due to: ' + status);
      }
   });
}
</pre>
<p>Los primeros 4 renglones de la función realizan la validación y separación de latitud y longitud, para poder formar el objeto latLng, y listo con esto tenemos terminado nuestro ejercicio, puedes verificarlo en funcionamiento en la página de demos:</p>
<p><a href="http://gmaps.alexfranco.mx/reverse-geocode"><img loading="lazy" decoding="async" class="aligncenter" title="Ver Demo Geocoding" src="http://sites.google.com/site/jafrancov/stuff/ver-demo.png" alt="Ver Demo Geocoding" width="140" height="57" /></a></p>
<p>El código completo quedaría así:</p>
<pre class="brush: jscript; title: ; notranslate">
var geocoder;
var map;
var infowindow = new google.maps.InfoWindow();
var marker = new google.maps.Marker();

function closeInfoWindow() {
      	infowindow.close();
   }

function initialize() {
  geocoder = new google.maps.Geocoder();
  var latlng = new google.maps.LatLng(20.68009, -101.35403);
  var mapOptions = {
    zoom: 8,
    center: latlng,
    mapTypeId: 'roadmap'
  }
  map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);

  google.maps.event.addListener(map, 'click', function(){
        	closeInfoWindow();
     	  });
}

function codeLatLng() {
  var input = $('#latlng').val();
  var latlngStr = input.split(',', 2);
  var lat = parseFloat(latlngStr&#x5B;0]);
  var lng = parseFloat(latlngStr&#x5B;1]);
  var latlng = new google.maps.LatLng(lat, lng);
  geocoder.geocode({'latLng': latlng}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      if (results&#x5B;0]) {
		map.fitBounds(results&#x5B;0].geometry.viewport);
                marker.setMap(map);
                marker.setPosition(latlng);
		$('#address').text(results&#x5B;0].formatted_address);
		infowindow.setContent(results&#x5B;0].formatted_address);
        infowindow.open(map, marker);
		google.maps.event.addListener(marker, 'click', function(){
            infowindow.setContent(results&#x5B;0].formatted_address);
	        infowindow.open(map, marker);
        });
      } else {
        alert('No results found');
      }
    } else {
      alert('Geocoder failed due to: ' + status);
    }
  });
}

$(document).ready(function(){
   initialize();
});
</pre>
<p>Y en el Body solamente esto:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div&gt;
   &lt;input id=&quot;latlng&quot; type=&quot;textbox&quot; value=&quot;20.68009, -101.35403&quot;&gt;
&lt;/div&gt;
&lt;div&gt;
   &lt;input type=&quot;button&quot; value=&quot;Reverse Geocode&quot; onclick=&quot;codeLatLng()&quot;&gt;
&lt;/div&gt;
&lt;table class=&quot;width2&quot;&gt;
   &lt;tr&gt;&lt;td class=&quot;unitx1&quot;&gt;&lt;strong&gt;Dirección:&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;div id=&quot;address&quot;&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;div id=&quot;map_canvas&quot; style=&quot;width: 990px; height: 500px&quot;&gt;&lt;/div&gt;
</pre>
<p>Espero les sirva y cualquier cosa, ya saben cómo contactarme&#8230;</p>
<p style="text-align: right;"><em>Enjoy this Life!</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jafrancov.com/2012/10/reverse-geocode/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2190</post-id>	</item>
		<item>
		<title>Buscar y trazar rutas con GMaps API v3</title>
		<link>https://jafrancov.com/2011/12/trazar-rutas-gmaps-api-v3/</link>
					<comments>https://jafrancov.com/2011/12/trazar-rutas-gmaps-api-v3/#comments</comments>
		
		<dc:creator><![CDATA[Alex Franco]]></dc:creator>
		<pubDate>Fri, 16 Dec 2011 19:41:28 +0000</pubDate>
				<category><![CDATA[Codigo]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Direcciones]]></category>
		<category><![CDATA[GMaps]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Maps]]></category>
		<category><![CDATA[Rutas]]></category>
		<guid isPermaLink="false">http://jafrancov.com/?p=2143</guid>

					<description><![CDATA[Si no tienes mucha experiencia o tienes dudas con respecto a algo que usemos en este post, puedes consultar los demás ejemplos que se han realizado anteriormente aquí. En esta ocasión veremos un ejemplo buscado por muchos, y que puede llegar a tener gran utilidad dependiendo de nuestra aplicación, estamos hablando de trazar rutas&#8230; dije ... <a title="Buscar y trazar rutas con GMaps API v3" class="read-more" href="https://jafrancov.com/2011/12/trazar-rutas-gmaps-api-v3/" aria-label="Leer más sobre Buscar y trazar rutas con GMaps API v3">Leer más</a>]]></description>
										<content:encoded><![CDATA[<p>Si no tienes mucha experiencia o tienes dudas con respecto a algo que usemos en este post, <a href="http://jafrancov.com/tag/gmaps">puedes consultar los demás ejemplos que se han realizado anteriormente aquí</a>.</p>
<p>En esta ocasión veremos un ejemplo buscado por muchos, y que puede llegar a tener gran utilidad dependiendo de nuestra aplicación, estamos hablando de trazar rutas&#8230; dije ¿rutas?, si, rutas, direcciones, un pequeño GPS en web.</p>
<p>Lo que haremos es bastante sencillo de entender y lo pondremos de la manera más básica, esto para darte la amplitud a que lo mejores y le pongas la cara que desees.</p>
<p>El proceso es entendido por todos, es proporcionar 2 puntos, un origen y un destino, a partir de esto, que nos proporcione una ruta para ir de un lado a otro. Sin más preámbulo manos a la obra.</p>
<p style="text-align: center;"><a href="http://gmaps.alexfranco.mx/routes-directions" target="_blank"><img loading="lazy" decoding="async" class="alignnone" title="Ver Demo Trazar Rutas" src="http://sites.google.com/site/jafrancov/stuff/ver-demo.png" alt="Ver Demo Single InfoWindow" width="140" height="57" /></a></p>
<p>Lo primero (siempre usaremos los scripts de jQuery y GMaps) que haremos será crear el html sobre el cuál vamos a trabajar, para esto solamente requerimos 2 cajas de texto para escribir el origen y el destino, un botón para ejecutar el proceso, 2 combobox donde uno será para elegir el modo de viaje (auto, bicicleta, caminando) y el otro para elegir el sistema de medición (Métrico -mts, Km-, Imperial -ft, Mi-), por último 2 divs, uno para el espacio del mapa y otro para el panel de direcciones.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div&gt;
	&lt;label for=&quot;origen&quot;&gt;Origen&lt;/label&gt;
	&lt;input type=&quot;text&quot; name=&quot;origen&quot; id=&quot;origen&quot; placeholder=&quot;calle, ciudad, estado...&quot; /&gt;
	&lt;br /&gt;
	&lt;label for=&quot;destino&quot;&gt;Destino&lt;/label&gt;
	&lt;input type=&quot;text&quot; name=&quot;destino&quot; id=&quot;destino&quot; placeholder=&quot;calle, ciudad, estado...&quot; /&gt;
	&lt;br /&gt;
	&lt;input type=&quot;button&quot; id=&quot;buscar&quot; value=&quot;Buscar ruta&quot;  /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;Opciones&lt;/h3&gt;
&lt;div id=&quot;rutaOps&quot;&gt;
	&lt;select id=&quot;modo_viaje&quot; class=&quot;opciones_ruta&quot;&gt;
		&lt;option value=&quot;DRIVING&quot; selected=&quot;selected&quot;&gt;Auto&lt;/option&gt;
      	&lt;option value=&quot;BICYCLING&quot;&gt;Bicicleta&lt;/option&gt;
      	&lt;option value=&quot;WALKING&quot;&gt;Caminando&lt;/option&gt;
  	&lt;/select&gt;
  	&lt;select id=&quot;tipo_sistema&quot; class=&quot;opciones_ruta&quot;&gt;
      	&lt;option value=&quot;METRIC&quot; selected=&quot;selected&quot;&gt;Métrico&lt;/option&gt;
      	&lt;option value=&quot;IMPERIAL&quot;&gt;Imperial&lt;/option&gt;
  	&lt;/select&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;
	&lt;div id=&quot;map_canvas&quot; style=&quot;float:left; width:70%; height:500px&quot;&gt;&lt;/div&gt;
	&lt;div id=&quot;panel_ruta&quot; style=&quot;float:right; overflow: auto; width:30%; height: 500px&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>Una vez que tenemos el HTML nos enfocaremos en el la API y JS completamente, declaramos 2 objetos globales, uno es <em>DirectionsRenderer</em> y otro es <em>DirectionsService</em>. El primero nos dará las herramientas necesarias para que visualicemos en el navegador toda la información obtenida, el segundo es el servicio que buscará en las bases de datos de Google Maps tanto los puntos como la(s) rutas existentes.</p>
<pre class="brush: jscript; title: ; notranslate">
var directionsDisplay = new google.maps.DirectionsRenderer();
var directionsService = new google.maps.DirectionsService();
</pre>
<p>Una vez hecho esto, escribimos el código para ya tener inicializado y dibujado el mapa en nuestra página, creamos una función con el nombre que nosotros queramos, dentro de ella, vamos a colocar lo siguiente:</p>
<pre class="brush: jscript; title: ; notranslate">
var request = {
 origin: $('#origen').val(),
 destination: $('#destino').val(),
 travelMode: google.maps.DirectionsTravelMode&#x5B;$('#modo_viaje').val()],
 unitSystem: google.maps.DirectionsUnitSystem&#x5B;$('#tipo_sistema').val()],
 provideRouteAlternatives: true
 };
</pre>
<p>Línea por línea:</p>
<ol>
<li>Declaramos una variable con las opciones con las que se va a solicitar la información al objeto <em>DirectionsServices</em>, lo siguiente son parámetros para hacer la búsqueda de acuerdo a los datos introducidos.</li>
<li>A <em>origin</em> se le asigna el valor de  la caja de texto <em>origen</em> estableciendo el punto de partida de la ruta.</li>
<li>A <em>destination</em> se le asigna el valor de la caja de texto <em>destino</em> con el que se especifica el punto final de la ruta.</li>
<li>En la opción <em>travelMode</em> se asigna la opción elegida para el modo de viaje (<em>modo_viaje</em>), por esta razón en el valor de cada opción se definió de acuerdo al valor asignado en la API.</li>
<li>unitSystem se refiere al tipo de unidades que se utilizarán para mostrar distancias, obteniendo el valor del <em>tipo_sistema</em>.</li>
<li>Con la opción provideRouteAlternatives establecemos en verdadero o falso (por default <em>false</em>), para indicar que puede ofrecernos más resultados para las rutas (rutas alternativas).</li>
</ol>
<p>Una vez declarada la variable con el arreglo de los parámetros, con unas cuántas líneas vamos a hacer la solicitud y plasmar el resultado:</p>
<pre class="brush: jscript; title: ; notranslate">
directionsService.route(request, function(response, status) {
	if (status == google.maps.DirectionsStatus.OK) {
		directionsDisplay.setMap(map);
		directionsDisplay.setPanel($(&quot;#panel_ruta&quot;).get(0));
		directionsDisplay.setDirections(response);
	} else {
	        alert(&quot;No existen rutas entre ambos puntos&quot;);
	}
});
</pre>
<p>Recordemos que al inicio declaramos 2 objetos, teniendo en cuenta su función, les explico línea a línea:</p>
<ol>
<li><em>directionsService.route</em> hace la solicitud a la API con los datos que previamente establecimos (<em>request</em>), creamos una una función interna, que recibe los parámetros de respuesta (<em>response</em>) que es donde vendrían contenidos los datos y un estatus (<em>status</em>) que indica si fue exitosa la solicitud.</li>
<li>Si el estatus es <em>OK</em> procedemos, si no, mandamos un mensaje de error diciendo que no se pudo encontrar ruta entre ambos puntos. Existe una serie de estatus distintos, sin embargo y para efectos prácticos solamente usamos aquí el OK (para ver más tipos de status, hay que ir directamente a la documentación de la API).</li>
<li><em>directionsDisplay.setMap(map)</em> establece el mapa sobre el cuál será trazada la ruta, la variable <em>map</em> debe ser un objeto tipo <a title="Primeros pasos con la API v3 de Google Maps (Mapa y Marcador)" href="http://jafrancov.com/2010/08/bases-gmaps-api-v3/" target="_blank">Mapa</a>, además de global.</li>
<li><em>directionsDisplay.setPanel($(&#8220;#panel_ruta&#8221;).get(0))</em> indica dónde van a ser escritas las indicaciones de la ruta, aquí es necesario indicar un div disponible (<em>panel_ruta</em>).</li>
<li>directionsDisplay.setDirections(response) hace la magia, imprime en el mapa la ruta y escribe las indicaciones de acuerdo a las 2 instrucciones anteriores.</li>
</ol>
<p>Por último solamente creamos un par de funciones para que al hacer click en el botón busque la ruta o la redibuje si se eligen diferentes opciones, esto es opcional, si no lo quieren así hay que hacer que indicar que al hacer click, la función central se ejecute, para mi caso, la función la llamé <em>rockAndRoll</em>  😀</p>
<pre class="brush: jscript; title: ; notranslate">
$('#buscar').live('click', function(){
	rockAndRoll();
});

$('.opciones_ruta').live('change', function(){
	rockAndRoll();
});
</pre>
<p style="text-align: center;"><a href="http://gmaps.alexfranco.mx/routes-directions" target="_blank"><img loading="lazy" decoding="async" title="Ver Demo Trazar Rutas" src="http://sites.google.com/site/jafrancov/stuff/ver-demo.png" alt="Ver Demo Single InfoWindow" width="140" height="57" /></a></p>
<p>Es todo por esta ocasión, espero les ayude en sus proyectos o simplemente para jugar un rato, si quieren verlo en función denle click en el botón verde, dudas y comentarios son bien recibidos, o pueden encontrarme en twitter @<a href="http://twitter.com/jafrancov" target="_blank">jafrancov</a></p>
<p style="text-align: right;"><em>Enjoy this Life!!</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jafrancov.com/2011/12/trazar-rutas-gmaps-api-v3/feed/</wfw:commentRss>
			<slash:comments>101</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2143</post-id>	</item>
		<item>
		<title>Geocode Simple: Buscar direcciones (coordenadas a partir de direcciones) con GMaps API v3</title>
		<link>https://jafrancov.com/2011/06/geocode-gmaps-api-v3/</link>
					<comments>https://jafrancov.com/2011/06/geocode-gmaps-api-v3/#comments</comments>
		
		<dc:creator><![CDATA[Alex Franco]]></dc:creator>
		<pubDate>Mon, 27 Jun 2011 01:29:33 +0000</pubDate>
				<category><![CDATA[Codigo]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Direcciones]]></category>
		<category><![CDATA[Geocode]]></category>
		<category><![CDATA[Geocoding]]></category>
		<category><![CDATA[GMaps]]></category>
		<category><![CDATA[Maps]]></category>
		<guid isPermaLink="false">http://jafrancov.com/?p=2091</guid>

					<description><![CDATA[Si no tienes mucha experiencia o tienes dudas con respecto a algo que usemos en este post, puedes consultar los demás ejemplos que se han realizado anteriormente aquí. Ya hemos visto el cómo obtener geolocalización para ubicar el lugar donde nos encontramos, pero, ¿qué pasa cuando buscamos una dirección diferente a donde nos encontramos?, sería ... <a title="Geocode Simple: Buscar direcciones (coordenadas a partir de direcciones) con GMaps API v3" class="read-more" href="https://jafrancov.com/2011/06/geocode-gmaps-api-v3/" aria-label="Leer más sobre Geocode Simple: Buscar direcciones (coordenadas a partir de direcciones) con GMaps API v3">Leer más</a>]]></description>
										<content:encoded><![CDATA[<p>Si no tienes mucha experiencia o tienes dudas con respecto a algo que usemos en este post,<a href="http://jafrancov.com/tag/gmaps"> puedes consultar los demás ejemplos que se han realizado anteriormente aquí</a>.</p>
<p>Ya hemos visto el <a href="http://jafrancov.com/2010/07/geolocalizacion-con-html5/">cómo obtener geolocalización</a> para ubicar el lugar donde nos encontramos, pero, ¿qué pasa cuando buscamos una dirección diferente a donde nos encontramos?, sería necesario escribir y buscar la dirección deseada, bien pues el proceso es relativamente sencillo. (Para esto requeriremos que agregues los scripts de GMaps y de jQuery, consulta los anteriores post si tienes duda de esto).</p>
<p>Lo que haremos se resume en: escribir una dirección, verificar si existe, si existe, colocar un marcador, centrar y dar zoom en el mapa en la región de la dirección obtenida, si no existe la dirección arrojar un error diciendo que no existe.</p>
<p style="text-align: center;"><a href="http://gmaps.alexfranco.mx/geocode-simple"><img loading="lazy" decoding="async" class="alignnone" title="Ver Demo Geocoding" src="http://sites.google.com/site/jafrancov/stuff/ver-demo.png" alt="Ver Demo Geocoding" width="140" height="57" /></a></p>
<p>La parte importante del código es generar un objeto que nos permita comunicarnos con la API  de Google Maps y nos convierta la dirección en latitud y longitud de manera que podamos maniobrarlas a placer.</p>
<pre class="brush: jscript; title: ; notranslate">var geocoder = new google.maps.Geocoder();</pre>
<p>Cuando se genera una petición de Geocoding, pueden enviarse varios parámetros para obtener resultados más específicos, un objeto de solicitud completa comprendería:</p>
<ul>
<li><em>address</em> (obligatorio *): es la dirección que deseas codificar de forma geográfica.</li>
<li><em>latLng</em> (obligatorio *): la latitud y la longitud (LatLng ) para las que deseas obtener la dirección interpretable por humanos más cercana.</li>
<li>bounds (opcional): los límites de latitud y de longitud (LatLngBounds) dentro de los que quieres predeterminar los resultados de codificación geográfica con mayor importancia. Para obtener más información, consulta la sección Especificación de la ventana gráfica que encontrarás a continuación.</li>
<li>language (opcional): es el idioma en el que se devuelven los resultados.</li>
<li>region (opcional): el código de región, especificado como una subetiqueta region del lenguaje IANA. En la mayoría de los casos, estas etiquetas se asignan directamente a valores de dos caracteres ccTLD (&#8220;dominio de nivel superior&#8221;) ya conocidos. Para obtener más información, consulta la sección Especificación del código de región que encontrarás a continuación.</li>
</ul>
<p>* <em>Nota</em>: la búsqueda funciona incluyendo solamente el campo address, aunque siempre es requisito incluir un campo address o un campo latLng obligatoriamente, si se coloca un campo latLng, el geocoder realizará el proceso conocido como codificación geográfica inversa, o sea, convertir coordenadas en direcciones, pero, eso lo veremos en otro post.</p>
<p>La solicitud se hace de la siguiente manera:</p>
<pre class="brush: jscript; title: ; notranslate">
// Obtenemos la dirección y la asignamos a una variable
var address = $('#address').val();
// Creamos el Objeto Geocoder
var geocoder = new google.maps.Geocoder();
// Hacemos la petición indicando la dirección e invocamos la función
// geocodeResult enviando todo el resultado obtenido
geocoder.geocode({ 'address': address}, geocodeResult);
</pre>
<p>El objeto que se obtiene de respuesta es un JSON, donde lo manejaríamos como regularmente se hace en javascript, el resultado es algo como esto:</p>
<pre class="brush: jscript; title: ; notranslate">
{
  &quot;status&quot;: &quot;OK&quot;,
  &quot;results&quot;: &#x5B; {
    &quot;types&quot;: &#x5B; &quot;street_address&quot; ],
    &quot;formatted_address&quot;: &quot;1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA&quot;,
    &quot;address_components&quot;: &#x5B; {
      &quot;long_name&quot;: &quot;1600&quot;,
      &quot;short_name&quot;: &quot;1600&quot;,
      &quot;types&quot;: &#x5B; &quot;street_number&quot; ]
    }, {
      &quot;long_name&quot;: &quot;Amphitheatre Pkwy&quot;,
      &quot;short_name&quot;: &quot;Amphitheatre Pkwy&quot;,
      &quot;types&quot;: &#x5B; &quot;route&quot; ]
    }, {
      &quot;long_name&quot;: &quot;Mountain View&quot;,
      &quot;short_name&quot;: &quot;Mountain View&quot;,
      &quot;types&quot;: &#x5B; &quot;locality&quot;, &quot;political&quot; ]
    }, {
      &quot;long_name&quot;: &quot;California&quot;,
      &quot;short_name&quot;: &quot;CA&quot;,
      &quot;types&quot;: &#x5B; &quot;administrative_area_level_1&quot;, &quot;political&quot; ]
    }, {
      &quot;long_name&quot;: &quot;United States&quot;,
      &quot;short_name&quot;: &quot;US&quot;,
      &quot;types&quot;: &#x5B; &quot;country&quot;, &quot;political&quot; ]
    }, {
      &quot;long_name&quot;: &quot;94043&quot;,
      &quot;short_name&quot;: &quot;94043&quot;,
      &quot;types&quot;: &#x5B; &quot;postal_code&quot; ]
    } ],
    &quot;geometry&quot;: {
      &quot;location&quot;: {
        &quot;lat&quot;: 37.4219720,
        &quot;lng&quot;: -122.0841430
      },
      &quot;location_type&quot;: &quot;ROOFTOP&quot;,
      &quot;viewport&quot;: {
        &quot;southwest&quot;: {
          &quot;lat&quot;: 37.4188244,
          &quot;lng&quot;: -122.0872906
        },
        &quot;northeast&quot;: {
          &quot;lat&quot;: 37.4251196,
          &quot;lng&quot;: -122.0809954
        }
      }
    }
  } ]
}
</pre>
<p>Lo único que nos faltaría es el código para validar, interpretar y dibujar. Para esto, hay 3 cosas importantes que debemos tomar en cuenta del JSON que tenemos de respuesta:</p>
<ul>
<li><em>status</em>: contiene la respuesta del estado de la petición, si fue satisfactoria o si hubo algún error y que tipo de error.</li>
<li><em>geometry.location</em>: la ubicación de la dirección solicitada</li>
<li><em>geometry.viewport</em>: los límites recomendados para ajustar el zoom del mapa, haciendo un cuadrante con las esquinas Noreste (superior derecha) y Suroeste (inferior izquierda).</li>
</ul>
<p>Con esto en presente, la función siguiente nos mostrará solamente el primer resultado obtenido, quedando así :</p>
<pre class="brush: jscript; title: ; notranslate">
function geocodeResult(results, status) {
    // Verificamos el estatus
    if (status == 'OK') {
        // Si hay resultados encontrados, centramos y repintamos el mapa
        // esto para eliminar cualquier pin antes puesto
        var mapOptions = {
            center: results&#x5B;0].geometry.location,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        map = new google.maps.Map($(&quot;#map_canvas&quot;).get(0), mapOptions);
        // fitBounds acercará el mapa con el zoom adecuado de acuerdo a lo buscado
        map.fitBounds(results&#x5B;0].geometry.viewport);
        // Dibujamos un marcador con la ubicación del primer resultado obtenido
        var markerOptions = { position: results&#x5B;0].geometry.location }
        var marker = new google.maps.Marker(markerOptions);
        marker.setMap(map);
    } else {
        // En caso de no haber resultados o que haya ocurrido un error
        // lanzamos un mensaje con el error
        alert(&quot;Geocoding no tuvo éxito debido a: &quot; + status);
    }
}
</pre>
<p>Y listo con esto tenemos terminado nuestro ejercicio, puedes verificarlo en funcionamiento en la página de demos:</p>
<p style="text-align: center;"><a href="http://gmaps.alexfranco.mx/geocode-simple"><img loading="lazy" decoding="async" class="alignnone" title="Ver Demo Geocoding" src="http://sites.google.com/site/jafrancov/stuff/ver-demo.png" alt="Ver Demo Geocoding" width="140" height="57" /></a></p>
<p>El código completo quedaría así:</p>
<pre class="brush: jscript; title: ; notranslate">
$(document).ready(function() {
    load_map();
});

var map;

function load_map() {
    var myLatlng = new google.maps.LatLng(20.68009, -101.35403);
    var myOptions = {
        zoom: 4,
        center: myLatlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map($(&quot;#map_canvas&quot;).get(0), myOptions);
}

$('#search').live('click', function() {
    // Obtenemos la dirección y la asignamos a una variable
    var address = $('#address').val();
    // Creamos el Objeto Geocoder
    var geocoder = new google.maps.Geocoder();
    // Hacemos la petición indicando la dirección e invocamos la función
    // geocodeResult enviando todo el resultado obtenido
    geocoder.geocode({ 'address': address}, geocodeResult);
});

function geocodeResult(results, status) {
    // Verificamos el estatus
    if (status == 'OK') {
        // Si hay resultados encontrados, centramos y repintamos el mapa
        // esto para eliminar cualquier pin antes puesto
        var mapOptions = {
            center: results&#x5B;0].geometry.location,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        map = new google.maps.Map($(&quot;#map_canvas&quot;).get(0), mapOptions);
        // fitBounds acercará el mapa con el zoom adecuado de acuerdo a lo buscado
        map.fitBounds(results&#x5B;0].geometry.viewport);
        // Dibujamos un marcador con la ubicación del primer resultado obtenido
        var markerOptions = { position: results&#x5B;0].geometry.location }
        var marker = new google.maps.Marker(markerOptions);
        marker.setMap(map);
    } else {
        // En caso de no haber resultados o que haya ocurrido un error
        // lanzamos un mensaje con el error
        alert(&quot;Geocoding no tuvo éxito debido a: &quot; + status);
    }
}
</pre>
<p>Y en el Body solamente esto:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div&gt;&lt;input type=&quot;text&quot; maxlength=&quot;100&quot; id=&quot;address&quot; placeholder=&quot;Dirección&quot; /&gt; &lt;input type=&quot;button&quot; id=&quot;search&quot; value=&quot;Buscar&quot; /&gt;&lt;/div&gt;&lt;br/&gt;
&lt;div id='map_canvas' style=&quot;width:600px; height:400px;&quot;&gt;&lt;/div&gt;
</pre>
<p>Espero les sirva y cualquier cosa, ya saben cómo contactarme&#8230;</p>
<p style="text-align: right;"><em>Enjoy this Life!</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jafrancov.com/2011/06/geocode-gmaps-api-v3/feed/</wfw:commentRss>
			<slash:comments>76</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2091</post-id>	</item>
	</channel>
</rss>
