//inicializamos foundation
$(document).ready(function () {
$(document).foundation();
});
//<![CDATA[
var map;
var markers = [];
var infoWindow;
var sidebarData;
//cargamos el mapa, lo colocamos en españa e inicializamos el infowindows
function load()
{
var styles =
[
{
stylers: [
{ hue: «#330» },
{ saturation: –20 }
]
},{
featureType: «road»,
elementType: «geometry»,
},{
featureType: «road»,
elementType: «labels»,
stylers: [
{ visibility: «on» }
]
}
];
map = new google.maps.Map(document.getElementById(«map»), {
center: new google.maps.LatLng(40.674389,–4.700432),
zoom: 6
});
map.setOptions({styles: styles});
infoWindow = new google.maps.InfoWindow();
//creamos el evento para que al pulsar el sidebar se abra el
//infowindow con la información de la tienda
$(document).on(«click», «#sidebar div p», function()
{
var markerNum = $(this).attr(«value»);
if (markerNum != «none»)
{
google.maps.event.trigger(markers[markerNum], ‘click’);
}
})
}
//al pulsar en buscar lo esta es la función que debe lanzar googlemaps
function buscaLocalizacion()
{
var address = document.getElementById(«addressInput»).value;
var geocoder = new google.maps.Geocoder();
geocoder.geocode({address: address}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
localizador(results[0].geometry.location);
} else {
alert(‘Su búsqueda no ha podido ser procesada.’);
}
});
}
//función para eliminar los infowindows y los markers antes de limpiarlos
function eliminarLocalizacion()
{
infoWindow.close();
for (var i = 0; i < markers.length; i++)
{
markers[i].setMap(null);
}
markers.length = 0;
$(«#sidebar div»).html(«»);
}
function localizador(center)
{
//limpiamos los markers anteriores para pintarlos de nuevo
eliminarLocalizacion();
//asignamos a radius el valor del select seleccionaRadio
var radius = document.getElementById(‘seleccionaRadio’).value;
var tipo_comercio = document.getElementById(‘tipo_comercio’).value;
//hay que mejorarlo, si piden tipo_comercio vamos a un método, si no a otro
if(tipo_comercio.length > 2){
var searchUrl = ‘dataGmaps.php?lat=’ + center.lat() + ‘&lng=’ + center.lng() + ‘&radius=’ + radius + ‘&tipo_comercio=’ + tipo_comercio;
}else{
var searchUrl = ‘dataGmaps.php?lat=’ + center.lat() + ‘&lng=’ + center.lng() + ‘&radius=’ + radius;
}
downloadUrl(searchUrl, function(data)
{
var xml = parseXml(data);
var markerNodes = xml.documentElement.getElementsByTagName(«marker»);
var bounds = new google.maps.LatLngBounds();
//si no se ha encontrado ningún resultado mostramos un alert con un error y salimos de la función
if(markerNodes.length == 0)
{
popup_error();
return;
}else{
var sidebar = «»;
for (var i = 0; i < markerNodes.length; i++)
{
var name = markerNodes[i].getAttribute(«name»);
var address = markerNodes[i].getAttribute(«address»);
var localidad = markerNodes[i].getAttribute(«localidad»);
var distance = parseFloat(markerNodes[i].getAttribute(«distance»));
var descripcion = markerNodes[i].getAttribute(«descripcion»);
var latlng = new google.maps.LatLng
(
parseFloat(markerNodes[i].getAttribute(«lat»)),
parseFloat(markerNodes[i].getAttribute(«lng»))
);
//llamamos a la función createOption
sidebar += «<p class=’lista’ value=»+i+«>» + name + «</p>»;
//pintamos el marker y el infowindow de cada lugar
createMarker(latlng, name, address, localidad, descripcion);
bounds.extend(latlng);
}
$(«#sidebar div»).html(sidebar)
}
map.fitBounds(bounds);
});
}
//función que crea el marker en el mapa, por cada uno que encuentre en la base de datos
//hará una iteracion a este función
function createMarker(latlng, name, address,localidad,descripcion)
{
//html contiene los datos que queremos mostrar en
//el infowindow al pulsar sobre el marker
var html = «<div id=’content’>»;
html += «<h1 class=’subheader’>» + name + «</h1>»;
html += «<div class=’body_content’>»;
html += «<p><b>» + address + «</b></p><br />»;
html += «<p><b>» + name + «</b></p>»;
html += «<p><b>» + descripcion != «» ? descripcion : «» + «</b></p>»;
html += «</div>»;
//modificamos un poco el aspecto del marker
var marker = new google.maps.Marker({
icon: {
path: google.maps.SymbolPath.CIRCLE,
strokeColor: «yellow»,
scale: 8
},
title: name,
map: map,
position: latlng
});
//al pulsar en el marker, llenamos el infowindow con los datos
//de la variable html y lo abrimos a continuación
google.maps.event.addListener(marker, ‘click’, function()
{
var infowindowopts = {
maxWidth: 350,
minHeight: 300,
content: html
};
//añadimos el marker e infowindow al mapa
infoWindow.setOptions(infowindowopts);
infoWindow.open(map, marker);
});
markers.push(marker);
}
//función para hacer la petición ajax con javascript
function downloadUrl(url, callback)
{
var request = window.ActiveXObject ?
new ActiveXObject(‘Microsoft.XMLHTTP’) :
new XMLHttpRequest;
request.onreadystatechange = function()
{
if (request.readyState == 4)
{
request.onreadystatechange = doNothing;
callback(request.responseText, request.status);
}
};
request.open(‘GET’, url, true);
//añadimos la cabecera para que php entienda que es una petición ajax, seguridad
request.setRequestHeader(«X-Requested-With», «XMLHttpRequest»);
request.send(null);
}
//función para parsear los datos
function parseXml(str)
{
if (window.ActiveXObject)
{
var doc = new ActiveXObject(‘Microsoft.XMLDOM’);
doc.loadXML(str);
return doc;
} else if (window.DOMParser) {
return (new DOMParser).parseFromString(str, ‘text/xml’);
}
}
//mostramos un error si no hay resultados
function popup_error()
{
alert(«No se han encontrado resultados. Por favor, intente aumentar el radio o pruebe otra ubicación.»);
}
function doNothing() {}
//]]>
|
Aquí simplemente creamos el mapa con las configuraciones creadas y los añadimos a la vista index.php, tenemos funciones que se encargan de solicitar datos, otra de parsear el xml, pintar el marker y el infowindow en el mapa etc, y todo está explicado en el código, simplemente debemos fijarnos en cada sección y tratar de entenderlo.
Si ahora nos dirigimos al debemos ver el mapa con el formulario y el sidebar sin ningún problema, lo único que si intentamos hacer búsquedas no funcionará, ésto es por dos motivos, el primero es que no tenemos información en la base de datos, y el segundo que los archivos que le tienen que devolver información no han sido creados, así que creo que es un buen momento para crear la clase conexion y gmaps.
La clase conexion.class.php
Creamos un archivo en la carpeta clases llamado conexion.class.php y dentro colocamos el siguiente código con el cuál podremos establecer una conexión con nuestra base de datos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
<?php
class Conexion
{
private static $instancia;
private $dbh;
private function __construct()
{
try {
$this->dbh = new PDO(‘mysql:host=localhost;dbname=loc_tiendas’, ‘root’, »);
$this->dbh->exec(«SET CHARACTER SET utf8»);
$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e) {
print «Error!: « . $e->getMessage();
die();
}
}
public function prepare($sql)
{
return $this->dbh->prepare($sql);
}
public static function singleton_conexion()
{
if (!isset(self::$instancia)) {
$miclase = __CLASS__;
self::$instancia = new $miclase;
}
return self::$instancia;
}
// Evita que el objeto se pueda clonar
public function __clone()
{
trigger_error(‘La clonación de este objeto no está permitida’, E_USER_ERROR);
}
}
|
La clase gmaps.class.php
Por problemas, no se pueden colocar temporalmente los símbolos porcentaje en el código, así que en la línea 46 colocar $tipo_comercio = ‘porcentaje’.$tipo_comercio.’porcentaje’;, disculpar las molestias, en breve estará solucionado.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
<?php
require_once(«conexion.class.php»);
class Gmaps
{
private $dbh;
public function __construct()
{
$this->dbh = Conexion::singleton_conexion();
}
//consulta para buscar por zona
public function dataGmaps($center_lat,$center_lng,$radius)
{
try{
$sql = «SELECT direccion,nombre,lat,lng,descripcion,
(6371 * acos(cos(radians(?)) *
cos(radians(lat)) *
cos(radians(lng) – radians(?)) +
sin(radians(?)) *
sin(radians(lat)))) AS distance
FROM lugares
HAVING distance < ?
ORDER BY distance
LIMIT 0 , 20″;
$query = $this->dbh->prepare($sql);
$query->bindParam(1,$center_lat);
$query->bindParam(2,$center_lng);
$query->bindParam(3,$center_lat);
$query->bindParam(4,$radius);
$query->execute();
return $query->fetchAll();
}catch (PDOException $e) {
$e->getMessage();
}
}
//consulta para buscar por zona y tipo comercio
public function dataGmapsComercio($center_lat,$center_lng,$radius,$tipo_comercio)
{
try {
//linea tipo comercio
$sql = «SELECT direccion,nombre,lat,lng,descripcion,
(6371 * acos(cos(radians(?)) *
cos(radians(lat)) *
cos(radians(lng) – radians(?)) +
sin(radians(?)) *
sin(radians(lat)))) AS distance
FROM lugares
WHERE tipo_comercio LIKE ?
HAVING distance < ?
ORDER BY distance
LIMIT 0 , 20″;
$query = $this->dbh->prepare($sql);
$query->bindParam(1,$center_lat);
$query->bindParam(2,$center_lng);
$query->bindParam(3,$center_lat);
$query->bindParam(4,$tipo_comercio);
$query->bindParam(5,$radius);
$query->execute();
return $query->fetchAll();
}catch (PDOException $e) {
$e->getMessage();
}
}
//función para guardar un nuevo comercio en la base de datos
public function save_store($nombre,$direccion,$lat,$lng,$tipo_comercio,$descripcion)
{
try {
$sql = «INSERT INTO lugares(nombre,direccion,lat,lng,tipo_comercio,descripcion) VALUES(?,?,?,?,?,?)»;
$query = $this->dbh->prepare($sql);
$query->bindParam(1, $nombre);
$query->bindParam(2, $direccion);
$query->bindParam(3, $lat);
$query->bindParam(4, $lng);
$query->bindParam(5, $tipo_comercio);
$query->bindParam(6, $descripcion);
if($query->execute())
{
$this->dbh = null;
return true;
}
} catch (PDOException $e) {
$e->getMessage();
}
}
}
|
Ahora ya tenemos las clases para establecer la conexión a nuestra base de datos y para obtener e insertar datos, simplemente nos queda crear los archivos que la llaman, para obtener datos y mostrarlos en el mapa el archivo al que hacemos la petición es dataGmaps.php, así que sólo debemos crearlo en la raíz de la aplicación(esto no es recomendable, pero es para evitar más carpetas) y dentro colocamos el siguiente código.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
<?php
//comprobamos que sea una petición ajax
if(!empty($_SERVER[‘HTTP_X_REQUESTED_WITH’]) && strtolower($_SERVER[‘HTTP_X_REQUESTED_WITH’]) == ‘xmlhttprequest’)
{
require_once(«clases/gmaps.class.php»);
$gmaps = new Gmaps();
//obtenemos las variables que llegar por get
$center_lat = $_GET[«lat»];
$center_lng = $_GET[«lng»];
$radius = $_GET[«radius»];
//si nos piden por un tipo de comercio pedimos datos al método dataGmapsComercio
//en otro caso al método dataGmaps
if(isset($_GET[«tipo_comercio»]))
{
$tipo_comercio = $_GET[«tipo_comercio»];
$resultado = $gmaps->dataGmapsComercio($center_lat,$center_lng,$radius,$tipo_comercio);
}else{
$resultado = $gmaps->dataGmaps($center_lat,$center_lng,$radius);
}
//colocamos un encabezado tipo xml para googlemaps
header(«Content-type: text/xml»);
//Iniciamos el archivo XML, creamos el nodo padre que será markers
$dom = new DOMDocument(«1.0»);
$node = $dom->createElement(«markers»);
$parnode = $dom->appendChild($node);
//recorremos el resultado para devolver el xml añadiendo los nodos que queramos
foreach ($resultado as $row)
{
$node = $dom->createElement(«marker»);
$newnode = $parnode->appendChild($node);
$newnode->setAttribute(«name», $row[‘nombre’]);
$newnode->setAttribute(«address», $row[‘direccion’]);
$newnode->setAttribute(«lat», $row[‘lat’]);
$newnode->setAttribute(«lng», $row[‘lng’]);
$newnode->setAttribute(«distance», $row[‘distance’]);
$newnode->setAttribute(«descripcion», $row[‘descripcion’]);
}
//imprimimos el xml para que google maps pueda buscar
echo $dom->saveXML();
}else{
throw new Exception(«Error Processing Request», 1);
}
|
Bien bien, ahora si que podemos hacer peticiones a la base de datos, el problema es que no tenemos resultados para mostrar, así que ahora debemos crear el archivo add_store.php en la raíz del proyecto y dentro añadir el siguiente código, el cuál nos generará un formulario con google maps, pero en este caso haciendo uso del autocompletado que nos ofrece y un mapa donde reflejar la posición escogida, veamos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
<html>
<head>
<meta http-equiv=«content-type» content=«text/html; charset=utf-8»/>
<meta name=«viewport» content=«initial-scale=1.0, user-scalable=no» />
<title>Añadir una tienda al localizador</title>
<!–css foundation para los estilos del formulario–>
<link rel=«stylesheet» type=«text/css» href=«css/foundation.min.css»>
<link rel=«stylesheet» type=«text/css» href=«css/normalize.css»>
<script type=«text/javascript» src=«//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js»></script>
<!–js foundation para los estilos del formulario–>
<script type=«text/javascript» src=«js/foundation.js»></script>
<script type=«text/javascript» src=«js/foundation.forms.js»></script>
<script src=«https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places»></script>
<script type=«text/javascript» src=«js/add_store.js»></script>
<!–libreria gmaps–>
<style type=»text/css»>
#descripcion{
min-height: 150px;
margin-top: 10px;
margin-bottom: 10px;
resize: none;
}
</style>
</head>
<body>
<div class=«row large-12»>
<!–menú–>
<ul class=«breadcrumbs large-6 large-offset-3»>
<li><a href=«index.php»>Buscar tiendas</a></li>
</ul>
<!–h3–>
<div class=«large-6 large-offset-3 columns»>
<h3 class=«subheader»>Añadir una tienda al localizador</h3>
</div>
<!–formulario para enviar por post–>
<form name=«formElem» class=«custom» method=«post» action=«save_store.php»>
<!–campo autocompletado para encontrar localizaciones–>
<div class=«large-6 large-offset-3 columns»>
<label for=«searchTextField»>Introduce la ubicación de la tienda: </label>
<input id=«searchTextField» name=«direccion» type=«text» value=«»>
</div>
<!–mapa con los campos ocultos para guardar latitud y longitud al escoger una ubicación
con el autocompletado–>
<div class=«large-6 large-offset-3 columns»>
<div id=«map_canvas» style=«width: 360px; height: 300px; float:left»></div>
<input type=«hidden» name=«lat» id=«lat» value=«» />
<input type=«hidden» name=«lng» id=«lng» value=«» />
</div>
<!–input para escribir el nombre del comercio–>
<div class=«large-6 large-offset-3 columns»>
<label for=«nombre»>Nombre del comercio: </label>
<input type=«text» name=«nombre» id=«nombre»/>
</div>
<!–select con las posibilidades de tipos de comercio–>
<div class=«large-9 large-offset-3 columns»>
<label for=«tipo_comercio»>Escoge el tipo de comercio:</label>
<select id=«tipo_comercio» class=«large» name=«tipo_comercio»>
<option value=«restaurantes» selected>Restaurantes</option>
<option value=«zapatos»>Zapatos</option>
<option value=«comidas_rapidas»>Comida rápida</option>
<option value=«agencias_viajes»>Agencias de viajes</option>
<option value=«deportes»>Tiendas de deportes</option>
<option value=«gimnasios»>Gimnasios</option>
<option value=«informatica»>Informática</option>
</select>
</div>
<!–input para escribir el nombre del comercio–>
<div class=«large-6 large-offset-3 columns»>
<label for=«descripcion»>Describe tu negocio: </label>
<textarea name=«descripcion» id=«descripcion»></textarea>
</div>
<!–submit para procesar el formulario–>
<div class=«large-9 large-offset-1 columns»>
<input type=«submit» class=«button» value=«Guardar comercio»>
</div>
</form>
</div>
</body>
</html>
|
Si ahora accedemos a la siguiente url podremos ver el formulario, pero de forma incompleta, ésto es porque necesitamos escribir más js, en este caso para crear otro mapa y la funcionalidad del autocompletado, así que creamos un nuevo archivo en la carpeta js llamado add_store.js y dentro colocamos el siguiente código.
Te esperamos en los siguientes artículos en donde hablaremos mas acerca de estos temas, los cuales hoy en día son de vital importancia en el mundo de la tecnología.