<?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>mooontes.com &#187; programacion</title>
	<atom:link href="http://mooontes.com/category/programacion/feed/" rel="self" type="application/rss+xml" />
	<link>http://mooontes.com</link>
	<description></description>
	<lastBuildDate>Mon, 23 Jan 2012 18:15:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Conferencia PHP Profesional &#8211; Carlos Buenosvinos</title>
		<link>http://mooontes.com/2011/05/23/conferencia-php-profesional-carlos-buenosvinos/</link>
		<comments>http://mooontes.com/2011/05/23/conferencia-php-profesional-carlos-buenosvinos/#comments</comments>
		<pubDate>Mon, 23 May 2011 22:42:14 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=432</guid>
		<description><![CDATA[Si te interesa PHP, te recomiendo que busques como sea un par de horas libres y te veas la conferencia de Carlos Buenosvinos sobre las herramientas necesarias para programar en PHP profesionalmente, vale su peso en oro (y gracias de nuevo a decharlas.com!) Vídeo Vimeo Conferencia PHP Profesional y diapositivas]]></description>
			<content:encoded><![CDATA[<p>Si te interesa PHP, te recomiendo que busques como sea un par de horas libres y te veas la conferencia de Carlos Buenosvinos sobre las herramientas necesarias para programar en PHP profesionalmente, vale su peso en oro (y gracias de nuevo a <a href='http://www.decharlas.com'>decharlas.com</a>!)</p>
<p><a target='_blank' href='http://decharlas.uji.es/php-profesional.php'>Vídeo Vimeo Conferencia PHP Profesional y diapositivas</a></p>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2011/05/23/conferencia-php-profesional-carlos-buenosvinos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony2, tutorial para comenzar ultra-rápido</title>
		<link>http://mooontes.com/2011/03/27/symfony2-tutorial-para-comenzar-ultra-rapido/</link>
		<comments>http://mooontes.com/2011/03/27/symfony2-tutorial-para-comenzar-ultra-rapido/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 01:32:44 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=380</guid>
		<description><![CDATA[This post in english at http://en.mooontes.com/2011/03/27/symfony2-ultra-fast-start-tutorial/ NOTA: Este tutorial se ha realizado en Ubuntu 11.04 &#8211; Natty Narwhal, no se ha comprobado su funcionamiento en otros sistemas operativos. Esto es sólo una especie de chuleta de ejemplo por si se te olvida alguna cosa tras leer la documentación de symfony2, pero evidentemente es imprescindible leérsela [...]]]></description>
			<content:encoded><![CDATA[<p><em>This post in english at <a href="http://en.mooontes.com/2011/03/27/symfony2-ultra-fast-start-tutorial/">http://en.mooontes.com/2011/03/27/symfony2-ultra-fast-start-tutorial/</a></p>
<p>NOTA: Este tutorial se ha realizado en Ubuntu 11.04 &#8211; Natty Narwhal, no se ha comprobado su funcionamiento en otros sistemas operativos. Esto es sólo una especie de chuleta de ejemplo por si se te olvida alguna cosa tras leer la documentación de symfony2, pero evidentemente es imprescindible leérsela antes para saber de qué va todo esto <img src='http://mooontes.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  <a href="http://symfony.com/doc/2.0/book/index.html">http://symfony.com/doc/2.0/book/index.html</a></em></p>
<p>El código fuente utilizado está disponible en: <a href='https://github.com/montes/Adictos-Symfony2-Bundle' target='_blank'>https://github.com/montes/Adictos-Symfony2-Bundle</a></p>
<p>ACTUALIZACIÓN 23/5/2011: Actualizado para symfony2 beta2</p>
<p>&nbsp;</p>
<h2>1. Descarga</h2>
<p>Descarga Symfony2 Standard Edition (en el momento de escribir esto la BETA2): <a href='http://symfony.com/download' target='_blank'>http://symfony.com/download</a></p>
<p>Descomprime</p>
<pre class="brush: bash; title: ; notranslate">
tar -zxvf Symfony_Standard_Vendors_2.0.0BETA2.tgz
</pre>
<p>Y cambia los permisos de app/cache y app/logs para que sean escribibles por php, por ejemplo:</p>
<pre class="brush: bash; title: ; notranslate">
chmod 777 app/cache app/logs
</pre>
<p>Configura en tu servidor el directorio &#8220;<em>web/</em>&#8221; como raíz y ya deberías poder cargar la página de bienvenida de symfony2 desde <a target="_blank"  href="http://127.0.0.1/app_dev.php/">http://127.0.0.1/app_dev.php/</a></p>
<p><span id="more-380"></span></p>
<p>&nbsp;</p>
<h2>2. Configura la base de datos</h2>
<p>Configura <em>app/config/parameters.ini</em> con las opciones de tu base de datos (también lo puedes hacer desde <a href="http://127.0.0.1/app_dev.php/_configurator/">http://127.0.0.1/app_dev.php/_configurator/</a> ), para mysql sería algo así:</p>
<pre class="brush: plain; title: ; notranslate">
[parameters]
    database_driver=pdo_mysql
    database_host=localhost
    database_name=symfony2
    database_user=symfony2
    database_password=password
    mailer_transport=smtp
    mailer_host=localhost
    mailer_user=
    mailer_password=
    locale=en
    csrf_secret=op234j234j2424jojpfwesdcsdc
</pre>
<p>&nbsp;</p>
<h2>3. Crear nuestro primer bundle</h2>
<p>Ahora ya podemos crear un bundle:</p>
<pre class="brush: bash; title: ; notranslate">
php app/console init:bundle &quot;Montes\AdictosBundle&quot; src
</pre>
<p>Ahora toca añadir a <em>app/autoload.php</em> :</p>
<pre class="brush: php; title: ; notranslate">
$loader-&gt;registerNamespaces(array(
    'Montes'                         =&gt; __DIR__.'/../src',
    // ...
));
</pre>
<p>y añadir a <em>app/AppKernel.php</em> :</p>
<pre class="brush: php; title: ; notranslate">
    $bundles = array(
        // ...
        new Montes\AdictosBundle\MontesAdictosBundle(),
    );
</pre>
<p>&nbsp;</p>
<h2>4. Ruta</h2>
<p>Para que symfony2 sepa dónde enviar las peticiones, añadimos a <em>app/config/routing_dev.yml</em> :</p>
<pre class="brush: bash; title: ; notranslate">
homepage:
    pattern:  /adictos
    defaults: { _controller: MontesAdictosBundle:Default:index }
</pre>
<p>En este punto ya podemos cargar nuestro recién creado bundle yendo a: <a target="_blank" href="http://127.0.0.1/app_dev.php/adictos">http://127.0.0.1/app_dev.php/adictos</a></p>
<p>&nbsp;</p>
<h2>5. Controller</h2>
<p>El controller por defecto (<em>Montes/AdictosBundle/Controller/DefaultController.php</em>) ya nos lo ha creado Symfony2, ahora vamos a crear el controller StoreController.php</p>
<pre class="brush: php; title: ; notranslate">
//Montes/AdictosBundle/Controller/StoreController.php
&lt;?php

namespace Montes\AdictosBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class StoreController extends Controller
{
    /**
     * @Template()
     */
    public function indexAction($store)
    {
        return array('store' =&gt; $store);
    }
}
</pre>
<p>y añadimos a <em>app/config/routing_dev.yml</em></p>
<pre class="brush: bash; title: ; notranslate">
store:
    pattern: /adictos/{store}
    defaults: { _controller: MontesAdictosBundle:Store:index }
</pre>
<p>y una nueva plantilla de twig a <em>Montes/AdictosBundle/Resources/Views/Store/index.html.twig</em></p>
<pre class="brush: xml; title: ; notranslate">
So you want store &quot;{{ store }}&quot;?
</pre>
<p>Y ahora cargando <a target="_blank" href="http://127.0.0.1/app_dev.php/adictos/mi-tienda">http://127.0.0.1/app_dev.php/adictos/mi-tienda</a> obtendremos:</p>
<p><em>So you want store &#8220;mi-tienda&#8221;?</em></p>
<p>&nbsp;</p>
<h2>6. Modelo</h2>
<p><em>NOTA: Para entrar en detalle sobre Doctrine2 recomiendo <a target='_blank' href='http://parasitovirtual.wordpress.com/category/cursos-y-articulos/desarrollo-de-webs/php/doctrine/'>el blog de Francisco Belmonte</a>, una maravilla.</em></p>
<p><del datetime="2011-05-23T21:32:54+00:00">Primero añadimos a <em>app/config/config.yml</em> &#8220;<em>MontesAdictosBundle: ~</em>&#8220;</del> A partir de la BETA1 por defecto el mapping es automático.</p>
<p>Comenzamos con Doctrine, vamos a definir nuestro modelo para una tienda. Antes de nada, como aún no hemos creado ningún modelo tendremos que crear el directorio <em>Montes/AdictosBundle/Entity</em> que es donde los guardaremos todos.</p>
<p>Y ya podemos empezar, modelo para Store:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// Montes/AdictosBundle/Entity/Store.php

namespace Montes\AdictosBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Store
{
    /**
     * @ORM\Id
     * @ORM\Column(type=&quot;integer&quot;)
     * @ORM\GeneratedValue(strategy=&quot;AUTO&quot;)
     */
     protected $id;

    /**
     * @ORM\ManyToMany(targetEntity=&quot;Category&quot;)
     * @ORM\JoinTable(name=&quot;stores_categories&quot;,
     *      joinColumns={@ORM\JoinColumn(name=&quot;store_id&quot;, referencedColumnName=&quot;id&quot;)},
     *      inverseJoinColumns={@ORM\JoinColumn(name=&quot;category_id&quot;, referencedColumnName=&quot;id&quot;)})
     */
    protected $categories;

    /**
     * @ORM\Column(type=&quot;string&quot;, length=&quot;255&quot;)
     */
    protected $url;

    /**
     * @ORM\Column(type=&quot;string&quot;, length=&quot;255&quot;)
     */
    protected $name;

    /**
     * @ORM\Column(type=&quot;integer&quot;)
     */
    protected $clicks = 0;

    /**
     * @ORM\Column(type=&quot;boolean&quot;)
     */
    protected $validated = false;

    /**
     * @ORM\Column(type=&quot;integer&quot;)
     */
    protected $pcomments = 0;

    /**
     * @ORM\Column(type=&quot;integer&quot;)
     */
    protected $ncomments = 0;

    /**
     * @ORM\Column(type=&quot;boolean&quot;)
     */
    protected $active = false;

    /**
     * @ORM\Column(type=&quot;datetime&quot;, name=&quot;updated_at&quot;)
     */
    protected $updatedAt;

    /**
     * @ORM\Column(type=&quot;datetime&quot;, name=&quot;created_at&quot;)
     */
    protected $createdAt;

    public function __construct()
    {
        $this-&gt;categories = new \Doctrine\Common\Collections\ArrayCollection();
        $this-&gt;createdAt = new \DateTime();
        $this-&gt;updatedAt = new \DateTime();
    }
}
</pre>
<p>Modelo para Category:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// Montes/AdictosBundle/Entity/Category.php

namespace Montes\AdictosBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Category
{
    /**
     * @ORM\Id
     * @ORM\Column(type=&quot;integer&quot;)
     * @ORM\GeneratedValue(strategy=&quot;AUTO&quot;)
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity=&quot;Category&quot;, mappedBy=&quot;parent&quot;)
     */
    protected $children;

    /**
     * @ORM\ManyToOne(targetEntity=&quot;Category&quot;, inversedBy=&quot;children&quot;)
     * @ORM\JoinColumn(name=&quot;parent_id&quot;, referencedColumnName=&quot;id&quot;)
     * @ORM\Column(nullable=&quot;true&quot;)
     */
    protected $parent;

    /**
     * @ORM\ManyToMany(targetEntity=&quot;Store&quot;, mappedBy=&quot;categories&quot;)
     */
    protected $stores;

    /**
     * @ORM\Column(type=&quot;string&quot;, length=&quot;255&quot;)
     */
    protected $name;

    /**
     * @ORM\Column(type=&quot;string&quot;, length=&quot;255&quot;, name=&quot;url_string&quot;, unique=&quot;true&quot;)
     */
    protected $urlString;

    public function __construct()
    {
        $this-&gt;stores = new \Doctrine\Commmon\Collections\ArrayCollection();
    }
}
</pre>
<p>Y ahora vamos a consola y para generar las tablas en la base de datos ejecutamos:</p>
<pre class="brush: bash; title: ; notranslate">
php app/console doctrine:schema:create
</pre>
<p>y para completar nuestro modelo con sus getters/setters:</p>
<pre class="brush: bash; title: ; notranslate">
php app/console doctrine:generate:entities MontesAdictosBundle
</pre>
<p>&nbsp;</p>
<h2>7. Probando el modelo</h2>
<p>Vamos a cambiar la acción que muestra la tienda a su propia acción (storeAction) para hacer hueco al índice del store controller en indexAction, que ahora mostrará el total de tiendas que tenemos almacenadas en la BD.</p>
<pre class="brush: bash; title: ; notranslate">
# app/config/routing_dev.yml
store:
    pattern: /adictos/{store}
    defaults: { _controller: MontesAdictosBundle:Store:store }

store_index:
    pattern: /adictos/
    defaults: { _controller: MontesAdictosBundle:Store:index }
</pre>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// Montes/AdictosBundle/Controller/StoreController.php

namespace Montes\AdictosBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class StoreController extends Controller
{

    /**
     * @Template()
     */
    public function indexAction()
    {
        $em = $this-&gt;get('doctrine.orm.entity_manager');
        $stores = $em-&gt;createQuery('SELECT count(s.id) AS total FROM Montes\AdictosBundle\Entity\Store s')-&gt;getSingleScalarResult();
        return array('stores' =&gt; $stores);
    }

    /**
     * @Template()
     */
    public function storeAction($store)
    {
        return array('store' =&gt; $store);
    }
}
</pre>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- Montes/AdictosBundle/Resources/views/Store/index.html.twig --&gt;
We have a total of {{ stores }} stores.
</pre>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- Montes/AdictosBundle/Resources/views/Store/store.html.twig --&gt;
So you want store &quot;{{ store }}&quot;?
</pre>
<p>Ahora al cargar <a target="_blank" href="http://127.0.0.1/app_dev.php/adictos/">http://127.0.0.1/app_dev.php/adictos/</a> nos saldrá <em>We have a total of 0 stores</em> y al cargar <a target="_blank" href="http://127.0.0.1/app_dev.php/adictos/mi-tienda">http://127.0.0.1/app_dev.php/adictos/mi-tienda</a> nos saldrá <em>So you want store &#8220;mi-tienda&#8221;?</em><br />
<a href="http://github.com/montes/Adictos-Symfony2-Bundle"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://d3nwyuy0nl342s.cloudfront.net/img/e6bef7a091f5f3138b8cd40bc3e114258dd68ddf/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2011/03/27/symfony2-tutorial-para-comenzar-ultra-rapido/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Free Javascript Calendar / Datepicker adaptado a España</title>
		<link>http://mooontes.com/2010/03/07/javascript-calendar-datepicker/</link>
		<comments>http://mooontes.com/2010/03/07/javascript-calendar-datepicker/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 17:10:42 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[calendar]]></category>
		<category><![CDATA[datepicker]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=339</guid>
		<description><![CDATA[Necesitaba un calendario en javascript tipo pop-up para el proyecto que tengo entre manos y me he encontrado con Javascript Calendar que tiene muy buena pinta, pero que sólo tiene versión anglosajona así que lo he modificado para adaptarlo a mis necesidades: Días de la semana y meses en castellano Primer día de la semana [...]]]></description>
			<content:encoded><![CDATA[<p>Necesitaba un calendario en javascript tipo pop-up para el proyecto que tengo entre manos y me he encontrado con <a href="http://javascriptcalendar.org">Javascript Calendar</a> que tiene muy buena pinta, pero que sólo tiene versión anglosajona así que lo he modificado para adaptarlo a mis necesidades:</p>
<ol>
<li>Días de la semana y meses en castellano</li>
<li>Primer día de la semana Lunes</li>
<li>Formato de fecha dd-mm-yyyy</li>
<li>Posibilidad de darle un id al node (span) que crea</li>
<li>Posiblidad de pasarle el path de las imágenes por si queremos que sea distinto al original</li>
</ol>
<p>Para usar la versión modificada, debéis descargar primero la original de su página y luego sobreescribir &#8220;<em>jsDatePick.full.1.0.js</em>&#8221; con el modificado &#8220;<em>jsDatePick.full.1.0.spain.js</em>&#8221; <a href="http://mooontes.com/codigo/jsDatePick.full.1.0.spain.js">Javascript Calendar Spanish Version</a></p>
<p>Este sería un ejemplo de uso con las dos nuevas opciones (<em>id</em> y <em>path</em>):</p>
<pre lang='javascript'>		new JsDatePick({
			useMode:2,
			id:"idCalendarNode",
			path:"/mis-imagenes/",
			target:"beginDate"
		});
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2010/03/07/javascript-calendar-datepicker/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Maps API V3 (javascript)</title>
		<link>http://mooontes.com/2009/07/30/google-maps-api-v3-javascript-2/</link>
		<comments>http://mooontes.com/2009/07/30/google-maps-api-v3-javascript-2/#comments</comments>
		<pubDate>Thu, 30 Jul 2009 19:14:21 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[api v3]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[google maps api v3]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[reverse geocoding]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=319</guid>
		<description><![CDATA[Versión en español de este post Although the Google Maps API V3 is still quite green and much remains to be polished, it is quite usable and if you only need the basic features of Google Maps, then you can use it for your project, the new speed and usability at portable devices is a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://mooontes.com/2009/07/29/google-maps-api-v3-javascript/">Versión en español de este post</a></p>
<p>Although the Google Maps API V3 is still quite green and much remains to be polished, it is quite usable and if you only need the basic features of Google Maps, then you can use it for your project, the new speed and usability at portable devices is a plus.</p>
<p>This code is an example of the use of various techniques with javascript:</p>
<ul>
<li>Map centering at user&#8217;s location</li>
<li>Event capturing</li>
<li>Reverse Geocoding</li>
<li>Use of <a href="http://google-maps-utility-library-v3.googlecode.com/svn/tags/scrollwheelzoom/1.0/docs/examples.html">Nianwei&#8217;s library</a> scrollwheelzoom (still not officially supported in V3)</li>
</ul>
<p><span id="more-319"></span></p>
<h3 style="clear:both;padding:20px;width:200px;text-align:center;margin:0px auto;"><a href="http://mooontes.com/codigo/google_maps_api_v3_en.html" target="_blank">Test the code</a></h3>
<p>And here is the code (<a href="http://validator.w3.org/check?uri=http://mooontes.com/codigo/google_maps_api_v3_en.html">validated</a> XHTML with Doctype).</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
&lt;!--
** Created at 2009 July by Montes http://mooontes.com
** Under licence http://creativecommons.org/licenses/by/3.0/es/deed.es
**
** Google Maps API V3 javascript example
**
** Visitor's location map centering, event capturing,
** reverse geocoding &amp; Nianwei's scrollwheelzoom
**
**
** Creado en Julio de 2009 por Montes http://mooontes.com
** Bajo licencia http://creativecommons.org/licenses/by/3.0/es/deed.es
**
** Ejemplo de programación con Google Maps API V3
**
** Centrado del mapa en la ubicación del visitante, captura de eventos,
** reverse geocoding y uso de la libreria para hacer zoom con la rueda del ratón
--&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;es&quot; lang=&quot;es&quot;&gt;
&lt;head&gt;

	&lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1.0, user-scalable=no&quot; /&gt;
	&lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;

	&lt;title&gt;Test Google Maps API V3 -mooontes.com-&lt;/title&gt;

    &lt;style type=&quot;text/css&quot;&gt;
	html
	{
		border:0;
		padding:0;
		margin:0;
		width:100%;
		height:100%;
	}
	body
	{
		border:0;
		padding:0;
		margin:0;
		width:100%;
		height:100%;
	}
	#map_canvas
	{
		width:100%;
		height:100%;
	}
	#info
	{
		position:absolute;
		width:250px;
		height:250px;
		left:20px;
		top:300px;
		background-color:white;
		padding:5px;
		overflow:auto;
	}
    &lt;/style&gt;

	&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;http://maps.google.com/maps/api/js?sensor=false&quot;&gt;&lt;/script&gt;	

	&lt;script type=&quot;text/javascript&quot;&gt;
	var map;
	var geocoder;

	function initialize() {

		//Geocoder initialization &amp; visitor's location map centering
		geocoder = new google.maps.Geocoder();
		if (google.loader.ClientLocation)
		{
			//Search for visitor's latitude and longitude
			var latt = google.loader.ClientLocation.latitude;
			var longg = google.loader.ClientLocation.longitude;

			//Center the map at visitor's coordinates
			var latlng = new google.maps.LatLng(latt,longg);
		}
		else
		{
			//If we can't get visitor's coordinates, set Madrid as map center
			var latlng = new google.maps.LatLng(&quot;40.41153868&quot;,&quot;-3.70362707&quot;);
		}

		//Create the map
		var myOptions = {
		zoom: 5,
		center: latlng,
		mapTypeId: google.maps.MapTypeId.ROADMAP
		};
		map = new google.maps.Map(document.getElementById(&quot;map_canvas&quot;), myOptions);

		//Add a listener, it will activate when the map become fully loaded
		google.maps.event.addListener(map, 'bounds_changed',function()
			{
				//First div's update to show actual location details
				actualizaUbicacion();
				//Map fully loaded, clear the listener
				google.maps.event.clearListeners(map, 'bounds_changed');
				//And add two new events, one will update the div's info when user ends dragging the map and the other when map's zoom changes
				google.maps.event.addListener(map, 'dragend',function() { actualizaUbicacion() });
				google.maps.event.addListener(map, 'zoom_changed',function() { actualizaUbicacion() });
			}
		);

	}

	function actualizaUbicacion()
	{

		//Map's center coordinates we'll use for reverse geocoding
		var lattlng = map.getCenter();

		if (geocoder)
		{
			geocoder.geocode({'latLng': lattlng}, function(results, status)
			{
				if (status == google.maps.GeocoderStatus.OK)
				{
					if (results[1])
					{
						var reverse_geo = results[1];

						var text = &quot;&lt;a href='http://mooontes.com/2009/07/30/google-maps-api-v3-javascript-2/'&gt;Back to post at mooontes.com&lt;&quot;+&quot;/a&gt;&lt;br /&gt;&lt;br /&gt;Map center: &quot;
							+ map.getCenter()+ &quot;&lt;br /&gt;&lt;br /&gt;Reverse Geocoding:&lt;br /&gt;&quot;;
						if (reverse_geo.address_components[0]) { text = text + &quot;0: &quot; + reverse_geo.address_components[0].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[1]) { text = text + &quot;1: &quot; + reverse_geo.address_components[1].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[2]) { text = text + &quot;2: &quot; + reverse_geo.address_components[2].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[3]) { text = text + &quot;3: &quot; + reverse_geo.address_components[3].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[4]) { text = text + &quot;4: &quot; + reverse_geo.address_components[4].long_name + &quot;&lt;br /&gt;&quot;; }

						text = text + &quot;5: &quot; + reverse_geo.formatted_address;

						document.getElementById('info').innerHTML = text;
					}
				}
				else
				{
					document.getElementById('info').innerHTML = &quot;No hay información de Reverse Geocoding.&quot;;
				}
			});
		}
	}

	//--&gt;&lt;/script&gt;

&lt;/head&gt;
&lt;body onload=&quot;initialize()&quot;&gt;
	&lt;div id=&quot;map_canvas&quot;&gt;&lt;/div&gt;
	&lt;div id=&quot;info&quot;&gt;&lt;a href=&quot;http://mooontes.com/2009/07/30/google-maps-api-v3-javascript-2/&quot;&gt;Back to post at mooontes.com&lt;/a&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2009/07/30/google-maps-api-v3-javascript-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Maps API V3 (javascript)</title>
		<link>http://mooontes.com/2009/07/29/google-maps-api-v3-javascript/</link>
		<comments>http://mooontes.com/2009/07/29/google-maps-api-v3-javascript/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 20:07:52 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[api v3]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[google maps api v3]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[reverse geocoding]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=295</guid>
		<description><![CDATA[Aunque el API V3 de Google Maps aún está bastante verde y le falta mucho por pulir, ya es bastante usable y si sólo necesitamos las características básicas de Google Maps nos puede servir para nuestro proyecto. Este código es un ejemplo del uso de varias técnicas con javascript: Centrar el mapa en la ubicación [...]]]></description>
			<content:encoded><![CDATA[<p>Aunque el API V3 de Google Maps aún está bastante verde y le falta mucho por pulir, ya es bastante usable y si sólo necesitamos las características básicas de Google Maps nos puede servir para nuestro proyecto.</p>
<p>Este código es un ejemplo del uso de varias técnicas con javascript:</p>
<ul>
<li>Centrar el mapa en la ubicación del visitante</li>
<li>Captura de eventos</li>
<li>Reverse Geocoding</li>
<li>Uso de la <a href="http://google-maps-utility-library-v3.googlecode.com/svn/tags/scrollwheelzoom/1.0/docs/examples.html">librería de Nianwei</a> para hacer zoom con la rueda del ratón (aún no soportado oficalmente en la V3)</li>
</ul>
<p><span id="more-295"></span></p>
<h3 style="clear:both;padding:20px;width:200px;text-align:center;margin:0px auto;"><a href="http://mooontes.com/codigo/google_maps_api_v3.html" target="_blank">Probar el código</a></h3>
<p>Y aquí dejo el código, XHTML con doctype y <a href="http://validator.w3.org/check?uri=http://mooontes.com/codigo/google_maps_api_v3.html">validable</a>, a diferencia de lo que nos tiene acostumbrados google <img src='http://mooontes.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
&lt;!--
** Creado en Julio de 2009 por Montes http://mooontes.com
** Bajo licencia http://creativecommons.org/licenses/by/3.0/es/deed.es
**
** Ejemplo de programación con Google Maps API V3
**
** Centrado del mapa en la ubicación del visitante, captura de eventos,
** reverse geocoding y uso de la libreria para hacer zoom con la rueda del ratón
--&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;es&quot; lang=&quot;es&quot;&gt;
&lt;head&gt;

	&lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1.0, user-scalable=no&quot; /&gt;
	&lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;

	&lt;title&gt;Test Google Maps API V3 -mooontes.com-&lt;/title&gt;

    &lt;style type=&quot;text/css&quot;&gt;
	html
	{
		border:0;
		padding:0;
		margin:0;
		width:100%;
		height:100%;
	}
	body
	{
		border:0;
		padding:0;
		margin:0;
		width:100%;
		height:100%;
	}
	#map_canvas
	{
		width:100%;
		height:100%;
	}
	#info
	{
		position:absolute;
		width:250px;
		height:250px;
		left:20px;
		top:300px;
		background-color:white;
		padding:5px;
		overflow:auto;
	}
    &lt;/style&gt;

	&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;http://maps.google.com/maps/api/js?sensor=false&quot;&gt;&lt;/script&gt;	

	&lt;script type=&quot;text/javascript&quot;&gt;
	var map;
	var geocoder;

	function initialize() {

		//Inicializamos geocoder y centramos el mapa en la ubicación del visitante
		geocoder = new google.maps.Geocoder();
		if (google.loader.ClientLocation)
		{
			//Averiguamos latitud/longitud del visitante
			var latt = google.loader.ClientLocation.latitude;
			var longg = google.loader.ClientLocation.longitude;

			//Centramos el mapa en sus coordenadas
			var latlng = new google.maps.LatLng(latt,longg);
		}
		else
		{
			//Si no localizamos la ubicacion del visitante, centramos el mapa en Madrid
			var latlng = new google.maps.LatLng(&quot;40.41153868&quot;,&quot;-3.70362707&quot;);
		}

		//Creamos el mapa
		var myOptions = {
		zoom: 5,
		center: latlng,
		mapTypeId: google.maps.MapTypeId.ROADMAP
		};
		map = new google.maps.Map(document.getElementById(&quot;map_canvas&quot;), myOptions);

		//Añadimos un listener, se activará cuando el mapa esté totalmente cargado
		google.maps.event.addListener(map, 'bounds_changed',function()
			{
				//Primera actualización del div que muestra los detalles de la ubicacion actual
				actualizaUbicacion();
				//Al haber cargado totalmente el mapa, eliminamos este listener
				google.maps.event.clearListeners(map, 'bounds_changed');
				//Y añadimos dos, uno se activará cuando se termine de arrastrar el mapa y otro cuando se cambie el nivel de zoom
				google.maps.event.addListener(map, 'dragend',function() { actualizaUbicacion() });
				google.maps.event.addListener(map, 'zoom_changed',function() { actualizaUbicacion() });
			}
		);

	}

	function actualizaUbicacion()
	{

		//Coordenadas del centro del mapa que usaremos para el reverse geocoding
		var lattlng = map.getCenter();

		if (geocoder)
		{
			geocoder.geocode({'latLng': lattlng}, function(results, status)
			{
				if (status == google.maps.GeocoderStatus.OK)
				{
					if (results[1])
					{
						var reverse_geo = results[1];

						var text = &quot;&lt;a href='http://mooontes.com'&gt;mooontes.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Map center: &quot;
							+ map.getCenter()+ &quot;&lt;br /&gt;&lt;br /&gt;Reverse Geocoding:&lt;br /&gt;&quot;;
						if (reverse_geo.address_components[0]) { text = text + &quot;0: &quot; + reverse_geo.address_components[0].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[1]) { text = text + &quot;1: &quot; + reverse_geo.address_components[1].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[2]) { text = text + &quot;2: &quot; + reverse_geo.address_components[2].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[3]) { text = text + &quot;3: &quot; + reverse_geo.address_components[3].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[4]) { text = text + &quot;4: &quot; + reverse_geo.address_components[4].long_name + &quot;&lt;br /&gt;&quot;; }

						text = text + &quot;5: &quot; + reverse_geo.formatted_address;

						document.getElementById('info').innerHTML = text;
					}
				}
				else
				{
					document.getElementById('info').innerHTML = &quot;No hay información de Reverse Geocoding.&quot;;
				}
			});
		}
	}

	//--&gt;&lt;/script&gt;

&lt;/head&gt;
&lt;body onload=&quot;initialize()&quot;&gt;
	&lt;div id=&quot;map_canvas&quot;&gt;&lt;/div&gt;
	&lt;div id=&quot;info&quot;&gt;&lt;a href=&quot;http://mooontes.com&quot;&gt;mooontes.com&lt;/a&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2009/07/29/google-maps-api-v3-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ajustar el tamaño de las fotos en SMF (Simple Machines Forum)</title>
		<link>http://mooontes.com/2009/06/15/ajustar-el-tamano-de-las-fotos-en-smf-simple-machines-forum/</link>
		<comments>http://mooontes.com/2009/06/15/ajustar-el-tamano-de-las-fotos-en-smf-simple-machines-forum/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 13:43:11 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[smf]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=245</guid>
		<description><![CDATA[Si tienes un foro en SMF (Simple Machines Forum), una de las opciones que no deberías activar nunca es la de ajustar automáticamente el tamaño de las fotos, ya que implica que cada vez que alguien escribe un mensaje que incluye fotos, el servidor se descargará todas las fotos del mensaje para comprobar su tamaño [...]]]></description>
			<content:encoded><![CDATA[<p>Si tienes un foro en SMF (<a href="http://www.simplemachines.org">Simple Machines Forum</a>), una de las opciones que no deberías activar nunca es la de ajustar automáticamente el tamaño de las fotos, ya que implica que cada vez que alguien escribe un mensaje que incluye fotos, el servidor se descargará todas las fotos del mensaje para comprobar su tamaño antes de que el mensaje se publique, con la consiguiente pérdida de tiempo y de paciencia del usuario.</p>
<p>En nuestro caso tenemos un foro con SMF2 y un movimiento de unos 1.200 mensajes diarios, con lo que realizar esta tarea manualmente (que es la única alternativa que queda) se hace bastante pesado.</p>
<p>La solución que he encontrado es escribir un pequeño programa en PHP que se ejecutará una vez al día gracias a <a href="http://es.wikipedia.org/wiki/Cron_%28unix%29">cron</a> y que realizará esta tarea por nosotros.<br />
<span id="more-245"></span><br />
Lo que hace este script es comprobar el tamaño de las fotos de los mensajes que se han escrito durante las últimas 24 horas y en el caso de que el tamaño exceda los 800 pixels de ancho, sustituirá la etiqueta <em>[IMG]</em> por <em>[IMG width=800]</em>, lo que evitará esas fotos gigantes que estropean la normal lectura del foro, además nos enviará un correo con la lista de mensajes que haya modificado.</p>
<p>Este es el script (bajo <a href="http://creativecommons.org/licenses/by/3.0/es/deed.es">licencia CC</a> como es habitual por aquí). Sólo ha sido testeado con SMF2, aunque no creo que haya mucho problema para hacerlo funcionar con SMF1.</p>
<p>Para hacerlo funcionar en vuestro servidor sólo tenéis que modificar la primera línea <em>require_once</em> con la ruta de vuestro <em>Settings.php</em> de SMF, la segunda línea asignando la variable <em>$to</em> al correo donde queréis recibir el resumen diario de mensajes modificados y la tercera línea asignando a <em>$url_foro</em> la dirección de vuestro foro. Y luego por supuesto añadir la tarea para que se ejecute diariamente.</p>
<pre class="brush: php; title: ; notranslate">
	//***
	//Creado Junio 2009 por Montes http://mooontes.com
	//Bajo licencia http://creativecommons.org/licenses/by/3.0/es/deed.es
	//***
	require_once(&quot;/ruta/Settings.php&quot;);  //la configuracion de la BD la cogemos del archivo de configuracion de SMF
	$to = &quot;correo@mail.com&quot;;
	$url_foro = &quot;www.foro.com&quot;;

	$mysqli = new mysqli($db_server,$db_user,$db_passwd,$db_name);

	$mail = &quot;Fotos modificadas hoy &quot;.date(&quot;d/m/Y&quot;).&quot;\n\n&quot;;

	//Comprobamos conexion
	if (mysqli_connect_errno())
	{
		printf(&quot;Connect failed: %s\n&quot;, mysqli_connect_error());
		exit();
	}	

	//Buscamos todos los mensajes con fotos de las ultimas 24 horas
	$sql = &quot;SELECT id_msg,id_topic,body FROM smf_messages WHERE DATE(FROM_UNIXTIME(poster_time))&quot;.
			&quot;&gt; DATE_SUB(DATE(NOW()), INTERVAL 1 DAY) AND body LIKE '%[IMG]http%'&quot;;
	if ($result = $mysqli-&gt;query($sql))
	{
		while($row = $result-&gt;fetch_assoc())
		{
			$body = $row[&quot;body&quot;];
			echo &quot;\n****msg: &quot;.$row[&quot;id_msg&quot;].&quot; topic: &quot;.$row[&quot;id_topic&quot;].&quot;, buscando imagenes...\n\n&quot;;

			//Comprobamos imagen x imagen
			preg_match_all(&quot;%\[img\]([^\[]*)\[/img\]%i&quot;, $row[&quot;body&quot;], $encuentra, PREG_PATTERN_ORDER);
			for ($j = 0; $j &lt; count($encuentra[1]); $j++)
			{
				echo &quot;una foto: &quot;.$encuentra[1][$j].&quot;\n&quot;;
				if (list($ancho, $altura, $tipo, $atr) = getimagesize($encuentra[1][$j]))
				{
					echo &quot;ancho: &quot;.$ancho.&quot; alto: &quot;.$altura.&quot;\n&quot;;
					if ($ancho &gt; 800)
					{
						echo &quot;Tamanyo mayor de 800, vamos a reemplazar...\n&quot;;
						//Mas ancha de 800 pixels? anyadimos width=800
						$body = str_ireplace(&quot;[img]&quot;.$encuentra[1][$j].&quot;[/img]&quot;, &quot;[img width=800]&quot;.$encuentra[1][$j].&quot;[/img]&quot;, $body);
						//actualizamos en la bd
						$bodys = addslashes($body);
						$sql = &quot;UPDATE smf_messages SET body = '&quot;.$bodys.
							&quot;', modified_time=UNIX_TIMESTAMP(), modified_name='bot' WHERE id_msg = &quot;.$row[&quot;id_msg&quot;];
						$mysqli-&gt;query($sql);
						echo &quot;Actualizada la BD\n&quot;;
						$mail .= &quot;Modificada foto en: http://&quot;.$url_foro
						.&quot;/index.php?topic=&quot;.$row[&quot;id_topic&quot;].&quot;.msg&quot;.
						$row[&quot;id_msg&quot;].&quot;#msg&quot;.$row[&quot;id_msg&quot;].&quot;\n&quot;;
					}
				}
				else
				{
					echo &quot;Tamanyo desconocido\n&quot;;
				}
			}
		}
	}

    $result-&gt;close();
    unset($row);
    unset($sql);
    unset($query);

	if ($mail != &quot;Fotos modificadas hoy &quot;.date(&quot;d/m/Y&quot;).&quot;\n\n&quot;)
	{
		$subject = &quot;Fotos arregladas dimensiones &quot;.date(&quot;d/m/Y&quot;);
		if (mail($to, $subject, $mail))
		{
			echo(&quot;Mensaje enviado\n&quot;);
		}
		else
		{
			echo(&quot;Fallo al enviar mensaje...\n&quot;);
		}
	}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2009/06/15/ajustar-el-tamano-de-las-fotos-en-smf-simple-machines-forum/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

