PageSourceSearch

https://www.ponferrada.org/javaScript/mapsApi.js

js ponferrada.org collected 2026-10-02 06:25:37 UTC 226,310 bytes, 5,356 lines download raw bytes

1/** @namespace MapsApi */
2
3// Variables globales GMaps
4var cmMap_iconMarkerList = null; // Utilizada para guardar los marcadores para Google Maps de Proxia
5var cmMap_colorOverlayList = null; // Utilizada para guardar los colores para Google Maps de Proxia
6var cmMap_messages = {};	//Utilizada para guardar los mensajes para Google Maps de Proxia
7var cmMap_ajaxResourcesLoaded = false; // Utilizada para sabes si hemos cargado los recursos Google Maps de Proxia
8var cmMap_objects = new Array(); // Utilizada para guardar los mapas de Google Maps de Proxia
9var cmMap_rootWeb = (window.top)? window.top._rootWeb : _rootWeb; // Utilizada para guardar la ruta absoluta de Proxia
10var cmMap_currentWeb = (window.top)? window.top._currentWeb : _currentWeb; // Utilizada para guardar la web actual
11
12// Recuperamos la region del usuario actual
13var cmMap_region = "ES"; // Por defecto
14if(typeof(_userLocaleCountry) == 'string')
15	cmMap_region = _userLocaleCountry;
16else if(window.top && typeof(window.top._userLocaleCountry) == 'string')
17	cmMap_region = window.top._userLocaleCountry;
18
19// Recuperamos el idioma del usuario actual
20var cmMap_lang = "es"; // Por defecto
21if(typeof(_userLocaleLang) == 'string')
22	cmMap_lang = _userLocaleLang;
23else if(window.top && typeof(window.top._userLocaleLang) == 'string')
24	cmMap_lang = window.top._userLocaleLang;
25
26// Recuperamos el locale actual
27var cmMap_locale = "es_ES"; // Por defecto
28if(typeof(_userLocale) == 'string')
29	cmMap_locale = _userLocale;
30else if(window.top && typeof(window.top._userLocale) == 'string')
31	cmMap_locale = window.top._userLocale;
32
33// Recuperamos la plantilla personalizada para los infoWindow
34var cmMap_infoWindowTemplate = "html/list"; // Por defecto
35if(typeof(cmMap_customInfoWindowTemplate) == 'string')
36	cmMap_infoWindowTemplate = cmMap_customInfoWindowTemplate;
37else if(window.top && typeof(window.top.cmMap_customInfoWindowTemplate) == 'string')
38	cmMap_infoWindowTemplate = window.top.cmMap_customInfoWindowTemplate;
39
40// Comprobamos si tenemos ventana padre y si en ella tenemos alguna opcion personalizada para el proyecto actual
41if(window.top) {
42	if(typeof(cmMap_howToArrive) != 'boolean' && typeof(window.top.cmMap_howToArrive) == 'boolean') {
43		var cmMap_howToArrive = window.top.cmMap_howToArrive;
44	}
45	if(typeof(cmMap_showForm) != 'boolean' && typeof(window.top.cmMap_showForm) == 'boolean') {
46		var cmMap_showForm = window.top.cmMap_showForm;
47	}
48	if(typeof(cmMap_showSearchBox) != 'boolean' && typeof(window.top.cmMap_showSearchBox) == 'boolean') {
49		var cmMap_showSearchBox = window.top.cmMap_showSearchBox;
50	}
51	if(typeof(cmMap_LngCoord) != 'number' && typeof(window.top.cmMap_LngCoord) == 'number') {
52		var cmMap_LngCoord = window.top.cmMap_LngCoord;
53	}
54	if(typeof(cmMap_LatCoord) != 'number' && typeof(window.top.cmMap_LatCoord) == 'number') {
55		var cmMap_LatCoord = window.top.cmMap_LatCoord;
56	}
57	if(typeof(cmMap_zoom) != 'number' && typeof(window.top.cmMap_zoom) == 'number') {
58		var cmMap_zoom = window.top.cmMap_zoom;
59	}
60	if(typeof(cmMap_mapTypeId) != 'string' && typeof(window.top.cmMap_mapTypeId) == 'string') {
61		var cmMap_mapTypeId = window.top.cmMap_mapTypeId;
62	}
63	if(typeof(cmMap_maxWidthInfoWindow) != 'number' && typeof(window.top.cmMap_maxWidthInfoWindow) == 'number') {
64		var cmMap_maxWidthInfoWindow = window.top.cmMap_maxWidthInfoWindow;
65	}
66	if(typeof(cmMap_minZoomLevel) != 'number' && typeof(window.top.cmMap_minZoomLevel) == 'number') {
67		var cmMap_minZoomLevel = window.top.cmMap_minZoomLevel;
68	}
69	if(typeof(cmMap_customCenterAndZoom) != 'boolean' && typeof(window.top.cmMap_customCenterAndZoom) == 'boolean') {
70		var cmMap_customCenterAndZoom = window.top.cmMap_customCenterAndZoom;
71	}
72	if(typeof(cmMap_defaultOptions) != 'object' && typeof(window.top.cmMap_defaultOptions) == 'object') {
73		var cmMap_defaultOptions = window.top.cmMap_defaultOptions;
74	}
75	if(typeof(cmMap_defaultStyleOverlay) != 'object' && typeof(window.top.cmMap_defaultStyleOverlay) == 'object') {
76		var cmMap_defaultStyleOverlay = window.top.cmMap_defaultStyleOverlay;
77	}
78	if(typeof(cmMap_defaultImageMarkerOptions) != 'object' && typeof(window.top.cmMap_defaultImageMarkerOptions) == 'object') {
79		var cmMap_defaultImageMarkerOptions = window.top.cmMap_defaultImageMarkerOptions;
80	}
81	if(typeof(cmMap_defaultShadowMarkerOptions) != 'object' && typeof(window.top.cmMap_defaultShadowMarkerOptions) == 'object') {
82		var cmMap_defaultShadowMarkerOptions = window.top.cmMap_defaultShadowMarkerOptions;
83	}
84	if(typeof(cmMap_defaultImageClusterOptions) != 'object' && typeof(window.top.cmMap_defaultImageClusterOptions) == 'object') {
85		var cmMap_defaultImageClusterOptions = window.top.cmMap_defaultImageClusterOptions;
86	}
87	if(typeof(cmMap_defaultShadowClusterOptions) != 'object' && typeof(window.top.cmMap_defaultShadowClusterOptions) == 'object') {
88		var cmMap_defaultShadowClusterOptions = window.top.cmMap_defaultShadowClusterOptions;
89	}
90	if(typeof(cmMap_useUrlHash) != 'boolean' && typeof(window.top.cmMap_useUrlHash) == 'boolean') {
91		var cmMap_useUrlHash = window.top.cmMap_useUrlHash;
92	}
93}
94
95// Para saber si estamos en modo wizard o no. Por defecto no.
96if(typeof(wizardMode) != 'boolean') {
97	var wizardMode = false;
98}
99
100// Para saber si queremos sacar un enlace de como llegar en cada marcador
101if(typeof(cmMap_howToArrive) != 'boolean') {
102	var cmMap_howToArrive = false;
103}
104
105// Para saber si queremos mostrar el formulario de busqueda
106if(typeof(cmMap_showForm) != 'boolean') {
107	var cmMap_showForm = false;
108}
109
110// Para saber si queremos mostrar la caja de busqueda
111if(typeof(cmMap_showSearchBox) != 'boolean') {
112	var cmMap_showSearchBox = false;
113}
114
115// Para saber si queremos usar el hash en la url con los parametros del mapa para que persistan los datos de busqueda en la navegacion
116if(typeof(cmMap_useUrlHash) != 'boolean') {
117	var cmMap_useUrlHash = true;
118}
119
120// Podemos hacer especificas cada una de las siguientes opciones moviendo cada una
121// de las variables a otro fichero especifico del proyecto, por ejemplo javaScript.jsp
122if(typeof(cmMap_LngCoord) != 'number') {
123	var cmMap_LngCoord = -4.728387; // Longitud por defecto donde se centra el mapa
124}
125if(typeof(cmMap_LatCoord) != 'number') {
126	var cmMap_LatCoord = 41.652947; // Latitud por defecto donde se centra el mapa
127}
128if(typeof(cmMap_zoom) != 'number') {
129	var cmMap_zoom = 7; // Nivel de zoom por defecto
130}
131if(typeof(cmMap_mapTypeId) != 'string') {
132	var cmMap_mapTypeId = 'ROADMAP'; // Tipo de mapa por defecto
133}
134if(typeof(cmMap_maxWidthInfoWindow) != 'number') {
135	var cmMap_maxWidthInfoWindow = 'auto'; // Ancho maximo por defecto para el infoWindow de Google Maps
136}
137if(typeof(cmMap_minZoomLevel) != 'number') {
138	var cmMap_minZoomLevel = 3; // El zoom minimo permitido en Google Maps
139}
140if(typeof(cmMap_customCenterAndZoom) != 'boolean') {
141	var cmMap_customCenterAndZoom = false; // Para saber si tenemos que aplicar un zoom y centrado personalizados
142}
143if(typeof(cmMap_defaultOptions) != 'object') {
144	// Podemos especificar distintas opciones (Longitud,Latitud,Nivel de zoom) en funcion
145	// del class que coincida con el de alguna de las capas contenedoras de cada mapa
146	var cmMap_defaultOptions = {
147		"cmMap_AbstractKml": new Array(cmMap_LngCoord,cmMap_LatCoord,cmMap_zoom)
148	};
149}
150if(typeof(cmMap_defaultStyleOverlay) != 'object') {
151	// color,opacidad y anchura por defecto para zonas y lineas
152	var cmMap_defaultStyleOverlay = {
153		"strokeColor" : '#000000',
154		"strokeOpacity" : '1',
155		"strokeWeight" : '3',
156		"fillColor" : '#000000',
157		"fillOpacity":'0.4'
158	};
159}
160if(typeof(cmMap_defaultImageMarkerOptions) != 'object') {
161	// Marcador por defecto
162	var cmMap_defaultImageMarkerOptions = {
163		"markerImage" : ((typeof(globalGmarkerImage)=="undefined" || !globalGmarkerImage)?cmMap_rootWeb+'/imagenes/contents/gmarker.png':globalGmarkerImage),
164		"markerSize" : new Array(32, 37),
165		"markerOrigin" : null,
166		"markerAnchor" : new Array(15, 33)
167	};
168}
169if(typeof(cmMap_defaultShadowMarkerOptions) != 'object') {
170	// Sombra del marcador por defecto
171	var cmMap_defaultShadowMarkerOptions = {
172		"markerImage" :  ((typeof(globalGmarkerShadowImage)=="undefined" || !globalGmarkerShadowImage)?cmMap_rootWeb+'/imagenes/contents/gmarkerShadow.png':globalGmarkerShadowImage),
173		"markerSize" : new Array(51, 37),
174		"markerOrigin" : null,
175		"markerAnchor" : new Array(16, 33)
176	};
177}
178
179if(typeof(cmMap_defaultImageClusterOptions) != 'object') {
180	var cmMap_defaultImageClusterOptions = $.extend( {}, cmMap_defaultImageMarkerOptions );
181}
182
183if(typeof(cmMap_defaultShadowClusterOptions) != 'object') {
184	var cmMap_defaultShadowClusterOptions = $.extend( {}, cmMap_defaultShadowMarkerOptions );
185}
186
187/**
188 * Indica como es el icono por defecto de los marcadores de la ruta
189 * @type {google.maps.MarkerImage}
190 * @memberOf MapsApi
191 */
192var cmMap_defaultImageMarkerRoute = new google.maps.MarkerImage(
193	((typeof(globalGmarkerRouteImage)=="undefined" || !globalGmarkerRouteImage)?cmMap_rootWeb+'/imagenes/contents/gmarkerRoute.png':globalGmarkerRouteImage),
194	new google.maps.Size(11, 11),
195	null,
196	new google.maps.Point(5, 5)
197);
198
199/**
200 * Marcador por defecto
201 * @type {google.maps.MarkerImage}
202 * @memberOf MapsApi
203 */
204var cmMap_defaultImageMarker = new google.maps.MarkerImage(
205	cmMap_defaultImageMarkerOptions["markerImage"],
206	new google.maps.Size(cmMap_defaultImageMarkerOptions["markerSize"][0],cmMap_defaultImageMarkerOptions["markerSize"][1]),
207	cmMap_defaultImageMarkerOptions["markerOrigin"],
208	new google.maps.Point(cmMap_defaultImageMarkerOptions["markerAnchor"][0],cmMap_defaultImageMarkerOptions["markerAnchor"][1])
209);
210
211/**
212 * Sombra del marcador por defecto
213 * @type {google.maps.MarkerImage}
214 * @memberOf MapsApi
215 */
216var cmMap_defaultShadowMarker = new google.maps.MarkerImage(
217	cmMap_defaultShadowMarkerOptions["markerImage"],
218	new google.maps.Size(cmMap_defaultShadowMarkerOptions["markerSize"][0],cmMap_defaultShadowMarkerOptions["markerSize"][1]),
219	cmMap_defaultShadowMarkerOptions["markerOrigin"],
220	new google.maps.Point(cmMap_defaultShadowMarkerOptions["markerAnchor"][0],cmMap_defaultShadowMarkerOptions["markerAnchor"][1])
221);
222
223/**
224 * Cluster por defecto
225 * @type {google.maps.MarkerImage}
226 * @memberOf MapsApi
227 */
228var cmMap_defaultImageCluster = new google.maps.MarkerImage(
229	cmMap_defaultImageClusterOptions["markerImage"],
230	new google.maps.Size(cmMap_defaultImageClusterOptions["markerSize"][0],cmMap_defaultImageClusterOptions["markerSize"][1]),
231	cmMap_defaultImageClusterOptions["markerOrigin"],
232	new google.maps.Point(cmMap_defaultImageClusterOptions["markerAnchor"][0],cmMap_defaultImageClusterOptions["markerAnchor"][1])
233);
234
235/**
236 * Sombra del cluster por defecto
237 * @type {google.maps.MarkerImage}
238 * @memberOf MapsApi
239 */
240var cmMap_defaultShadowCluster = new google.maps.MarkerImage(
241	cmMap_defaultShadowClusterOptions["markerImage"],
242	new google.maps.Size(cmMap_defaultShadowClusterOptions["markerSize"][0],cmMap_defaultShadowClusterOptions["markerSize"][1]),
243	cmMap_defaultShadowClusterOptions["markerOrigin"],
244	new google.maps.Point(cmMap_defaultShadowClusterOptions["markerAnchor"][0],cmMap_defaultShadowClusterOptions["markerAnchor"][1])
245);
246
247
248/**
249 * VARIABLES PARA EL TIPO DE MAPA USUARIO
250 * parametro mapa
251 * editableMode:indicamos si estamos en modeo de creacion y edicion de mapas(en la opcion que ve el usuario es false)
252 * en esta opcion se pueden editar las formas, y arrastrar los marcadores, ruta
253 * typeParam:si estamos en modo de edicion indica que tipo de papametro es.si tipo mapa o tipo localizacion
254 * createRoutesMode:indica si va a haber opcion de crear rutas
255 * @type {{zoom: number, LatCoord: number, LngCoord: number, mapTypeId: string, editableMode: boolean, typeParam: string, createRoutesMode: boolean, defaultImageMarkerRoute: google.maps.MarkerImage, defaultImageMarker: google.maps.MarkerImage, defaultShadowMarker: google.maps.MarkerImage, defaultImageCluster: google.maps.MarkerImage, defaultShadowCluster: google.maps.MarkerImage, defaultStyleOverlay: {strokeColor: string, strokeOpacity: string, strokeWeight: string, fillColor: string, fillOpacity: string}}}
256 * @memberOf MapsApi
257 */
258var varTipoMapaUsuario = {
259	zoom:cmMap_zoom,
260	LatCoord:cmMap_LatCoord,
261	LngCoord:cmMap_LngCoord,
262	mapTypeId:cmMap_mapTypeId,
263	editableMode:false,
264	typeParam:'',
265	createRoutesMode:true,
266	defaultImageMarkerRoute:cmMap_defaultImageMarkerRoute,
267	defaultImageMarker:cmMap_defaultImageMarker,
268	defaultShadowMarker:cmMap_defaultShadowMarker,
269	defaultImageCluster:cmMap_defaultImageCluster,
270	defaultShadowCluster:cmMap_defaultShadowCluster,
271	defaultStyleOverlay:cmMap_defaultStyleOverlay
272};
273
274/**
275 * VARIABLES PARA EL TIPO DE MAPA LOCATION
276 * parametro location
277 * editableMode:indicamos si estamos en modeo de creacion y edicion de mapas(en la opcion que ve el usuario es false)
278 * en esta opcion se pueden editar las formas, y arrastrar los marcadores, ruta
279 * typeParam:si estamos en modo de edicion indica que tipo de papametro es.si tipo mapa o tipo localizacion
280 * createRoutesMode:indica si va a haber opcion de crear rutas
281 * @type {{zoom: number, LatCoord: number, LngCoord: number, mapTypeId: string, editableMode: boolean, typeParam: string, createRoutesMode: boolean, defaultImageMarkerRoute: google.maps.MarkerImage, defaultImageMarker: google.maps.MarkerImage, defaultShadowMarker: google.maps.MarkerImage, defaultImageCluster: google.maps.MarkerImage, defaultShadowCluster: google.maps.MarkerImage, defaultStyleOverlay: {strokeColor: string, strokeOpacity: string, strokeWeight: string, fillColor: string, fillOpacity: string}}}
282 * @memberOf MapsApi
283 */
284var varTipoMapaLocation = {
285	zoom:cmMap_zoom,
286	LatCoord:cmMap_LatCoord,
287	LngCoord:cmMap_LngCoord,
288	mapTypeId:cmMap_mapTypeId,
289	editableMode:true,
290	typeParam:'location',
291	createRoutesMode:false,
292	defaultImageMarkerRoute:cmMap_defaultImageMarkerRoute,
293	defaultImageMarker:cmMap_defaultImageMarker,
294	defaultShadowMarker:cmMap_defaultShadowMarker,
295	defaultImageCluster:cmMap_defaultImageCluster,
296	defaultShadowCluster:cmMap_defaultShadowCluster,
297	defaultStyleOverlay:cmMap_defaultStyleOverlay
298};
299
300
301/**
302 * VARIABLES PARA EL TIPO DE MAPA MAPA
303 * editableMode:indicamos si estamos en modeo de creacion y edicion de mapas(en la opcion que ve el usuario es false)
304 * en esta opcion se pueden editar las formas, y arrastrar los marcadores, ruta
305 * typeParam:si estamos en modo de edicion indica que tipo de papametro es.si tipo mapa o tipo localizacion
306 * createRoutesMode:indica si va a haber opcion de crear rutas
307 * @type {{zoom: number, LatCoord: number, LngCoord: number, mapTypeId: string, editableMode: boolean, typeParam: string, createRoutesMode: boolean, defaultImageMarkerRoute: google.maps.MarkerImage, defaultImageMarker: google.maps.MarkerImage, defaultShadowMarker: google.maps.MarkerImage, defaultImageCluster: google.maps.MarkerImage, defaultShadowCluster: google.maps.MarkerImage, defaultStyleOverlay: {strokeColor: string, strokeOpacity: string, strokeWeight: string, fillColor: string, fillOpacity: string}}}
308 * @memberOf MapsApi
309 */
310var varTipoMapaKml = {
311	zoom:cmMap_zoom,
312	LatCoord:cmMap_LatCoord,
313	LngCoord:cmMap_LngCoord,
314	mapTypeId:cmMap_mapTypeId,
315	editableMode:true,
316	typeParam:'map',
317	createRoutesMode:true,
318	defaultImageMarkerRoute:cmMap_defaultImageMarkerRoute,
319	defaultImageMarker:cmMap_defaultImageMarker,
320	defaultShadowMarker:cmMap_defaultShadowMarker,
321	defaultImageCluster:cmMap_defaultImageCluster,
322	defaultShadowCluster:cmMap_defaultShadowCluster,
323	defaultStyleOverlay:cmMap_defaultStyleOverlay
324};
325
326/**
327 *
328 * @param msg
329 * @param parameters
330 * @returns {*}
331 * @memberOf MapsApi
332 */
333function resolveMessageinGmaps(msg,parameters) {
334	var _message;
335	if(cmMap_messages[msg]) {
336		// Recuperamos el mensaje.
337		_message = cmMap_messages[msg];
338		// Tenemos que intentar reemplazar los datos en la cadena.
339		if(parameters) {
340			for(var n=0;n<parameters.length;n++) {
341				var re = new RegExp("@"+(n+1),"gm");
342				_message = _message.replace(re,parameters[n]);
343			}
344		}
345		return _message;
346	}
347	if(msg.message) return msg.message;
348	return msg;
349}
350
351/**
352 * Función que cambia que el campo link por el selector de contenido y viceversa en los radio buttons
353 * @param objChk
354 * @memberOf MapsApi
355 */
356function changeLinkType(objChk) {
357	if(!objChk.checked) objChk.checked = 'checked';
358	if(objChk.id == 'linkType_url') {
359		document.getElementById('linkUrl').style.display = 'block';
360		document.getElementById('linkContent').style.display = 'none';
361	}
362	else if(objChk.id == 'linkType_content') {
363		document.getElementById('linkUrl').style.display = 'none';
364		document.getElementById('linkContent').style.display = 'block';
365	}
366}
367
368/**
369 * Función que abre la ventana de búsqueda de contenidos
370 * @memberOf MapsApi
371 */
372function openSearchWindow() {
373	var urlToOpen = cmMap_rootWeb+"/cm/"+cmMap_currentWeb+"/wizard/tkContentSearcher";
374	window.top.openProxiaDialog({ title : resolveMessageinGmaps('{contentSearch}'), file : urlToOpen, width : 590, height : 460, inline : 1 });
375}
376
377/**
378 * Función que actualiza los datos del contenido una vez seleccionado uno en la ventana de búsqueda
379 * @param contentPK
380 * @param name
381 * @param idContent
382 * @param alias
383 * @param contentName
384 * @param contentAltText
385 * @memberOf MapsApi
386 */
387function activeNewContent(contentPK,name,idContent,alias,contentName,contentAltText) {
388	$("#linkText_content").val(name);
389	$("#link_idContent").val(idContent);
390	$("#link_alias").val(alias);
391	if($("#name").val() != '' || $("#description").val() != '') {
392		var myMessageBox = new window.top.MessageBox(300,130);
393		myMessageBox.setMessage(resolveMessageinGmaps('{sureReplaceMarkerInfo}'));
394		myMessageBox.addButton(window.top.resolveMessage('{lang_accept}'),function() {
395			$("#name").val(contentName);
396			$("#description").val(contentAltText);
397			window.top.hideLoadingLayer(document);
398		});
399		myMessageBox.addButton(window.top.resolveMessage('{lang_cancel}'));
400		myMessageBox.showWindow(document);
401	}
402	else {
403		$("#name").val(contentName);
404		$("#description").val(contentAltText);
405	}
406}
407
408/**
409 * Elimina el contenido seleccionado
410 * @memberOf MapsApi
411 */
412function cmMap_deleteContent() {
413	$("#linkText_content").val(resolveMessageinGmaps('{noContent}'));
414	$("#link_idContent").val('');
415	$("#link_alias").val('');
416}
417
418/**
419 * Función que convierte caracteres especiales en entidades
420 * @param {string} str - Cadena a tratar
421 * @returns {string} Cadena reemplazada
422 * @memberOf MapsApi
423 */
424function cmMap_encodeString(str) {
425	str = str.replace(/&/g, '&amp;');
426	str = str.replace(/'/g, '&apos;');
427	str = str.replace(/"/g, '&quot;');
428	str = str.replace(/</g, '&lt;');
429	str = str.replace(/>/g, '&gt;');
430	return str;
431}
432
433function cm_googleMap(datos){
434	var googleMapObject=this;
435	//flag que nos indica si ya ha cargado el mapa o no
436	googleMapObject.isLoaded = false;
437	//flag que nos indica si ya hemos realizado la primera llamada ajax de carga de puntos o no
438	googleMapObject.isAjaxLoaded = false;
439	//zoom del mapa que se muestra
440	googleMapObject.cmMap_zoom = datos.zoom;
441	//coordenadas donde se centra el mapa
442	googleMapObject.cmMap_LatCoord = datos.LatCoord;
443	googleMapObject.cmMap_LngCoord = datos.LngCoord;
444	//tipo de mapa
445	googleMapObject.cmMap_mapTypeId=datos.mapTypeId;
446	//array de marcadores pintados via json
447	googleMapObject.cmMap_jsonMarkers = new Array();
448	googleMapObject.cmMap_jsonPolys = new Array();
449	//selector con el formulario de busqueda, si existe
450	googleMapObject.cmMap_searchForm = null;
451
452	//en la version en la que se implemento este plugin, el numero maximo de waypoints en una ruta es 8(+inicio y fin ruta)
453	var cmMap_MaxWaypoints=8;
454	
455	//indicamos si estamos en modeo de creacion y edicion de mapas (en la opcion que ve el usuario es false)
456	//en esta opcion se pueden editar las formas, y arrastrar los marcadores, ruta
457	googleMapObject.cmMap_editableMode = datos.editableMode;
458	//si estamos en modo de edicion indica que tipo de papametro es.si tipo mapa o tipo localizacion
459	googleMapObject.cmMap_typeParam = datos.typeParam;
460	//si estamos en modo de edicion de tipo localizacion, solo podemos tener un marker
461	var cmMap_contMarkerInMap=0;
462	
463	//indica si va a haber opcion de crear rutas (en el ctipo de parametro map y cuando lo ve el usuario si)
464	googleMapObject.cmMap_createRoutesMode = datos.createRoutesMode;
465	//indica si se crean ventanas de informacion en los marcadores de rutas y como es el icono por defecto
466	//por defecto tenemos indicamos que se crea ventana de informacion para los marcadores si esta en modo edicion
467	var cmMap_createInfowinMarkerRoute=googleMapObject.cmMap_editableMode;
468	googleMapObject.cmMap_defaultImageMarkerRoute = datos.defaultImageMarkerRoute;
469	
470	/*marcador que no es de ruta por defecto*/
471	googleMapObject.cmMap_defaultImageMarker = datos.defaultImageMarker;
472	googleMapObject.cmMap_defaultShadowMarker = datos.defaultShadowMarker;
473	googleMapObject.cmMap_defaultImageCluster = datos.defaultImageCluster;
474	googleMapObject.cmMap_defaultShadowCluster = datos.defaultShadowCluster;
475	
476	//indicamos las opciones de los marcadores por defecto	
477	var cmMap_markerOptions={icon: googleMapObject.cmMap_defaultImageMarker,shadow:googleMapObject.cmMap_defaultShadowMarker,draggable:googleMapObject.cmMap_editableMode};
478	var cmMap_clusterOptions={icon: googleMapObject.cmMap_defaultImageCluster,shadow:googleMapObject.cmMap_defaultShadowCluster,draggable:googleMapObject.cmMap_editableMode};
479	var cmMap_markerOptionsInRoute={icon: googleMapObject.cmMap_defaultImageMarkerRoute,draggable:googleMapObject.cmMap_editableMode};
480	
481	/*colores,opacidades y anchuras por defecto para las zonas y lineas*/
482	googleMapObject.cmMap_defaultStyleOverlay = datos.defaultStyleOverlay;
483	
484	//se utiliza para obtener las coordenadas de una dirección
485	var cmMap_geocoder;
486	//div contenedor de las direcciones
487	var cmMap_directions;
488	//div contenedor del mapa
489	var cmMap_map;
490	//contoles del mapa
491	var cmMap_controls;
492	//ventana que esta abierta
493	var cmMap_oldInfoWindow=null;
494	//para centrar el mapa
495	var cmMap_bounds = new google.maps.LatLngBounds();
496	//para crear rutas
497	var cmMap_directionsDisplay;
498	var cmMap_directionsService = new google.maps.DirectionsService();
499	//para crear rutas por el usuario final
500	var cmMap_customDirectionsDisplay = null;
501	var cmMap_customDirectionsService = null;
502
503	//para crear ruta por carreteras (dibujar una linea a lo largo de las carreteras)
504	var rendererOptions = {
505		map: googleMapObject.cmMap,
506		preserveViewport:true,
507		draggable: googleMapObject.cmMap_editableMode,
508		suppressMarkers:true
509	}
510
511	// Contemplamos la posibilidad de anadir opciones personalizadas a la renderizacion de rutas
512	if(typeof(cmMap_myCustomRendererOptions) == 'function') {
513		$.extend(rendererOptions, cmMap_myCustomRendererOptions());
514	}
515	
516	// Opciones por defecto del mapa (por defecto modo mapa de carreteras y sin controles)
517	var myOptions = {
518		mapTypeId: google.maps.MapTypeId.ROADMAP,
519		disableDefaultUI: true
520	};
521
522	// Si no estamos en modo de edicion ocultamos los POIs
523	if(!googleMapObject.cmMap_editableMode) {
524		$.extend(myOptions, {
525			gestureHandling: 'cooperative',
526			styles: [{
527				featureType: "poi",
528				stylers: [{ visibility: "off" }]
529			}]
530		});
531	}
532
533	// Contemplamos la posibilidad de anadir opciones personalizadas a los mapas
534	if(typeof(cmMap_myCustomOptions) == 'function') {
535		$.extend(myOptions, cmMap_myCustomOptions());
536	}
537
538	//overlaysInMap guarda todos los overlays
539	var cmMap_overlaysInMap = {},cmMap_infoWindowInMap = {};
540	//para los markers que no estan en ruta
541	cmMap_overlaysInMap['markerNotInRoute']= new Array(),cmMap_infoWindowInMap['markerNotInRoute']= new Array();
542	//para los markers que estan en ruta
543	cmMap_overlaysInMap['markerInRoute']= new Array(),cmMap_infoWindowInMap['markerInRoute']= new Array();
544	var cmMap_markersRouteLatLng = new Array(),cmMap_initialMarkerRoute;
545	
546	//para el resto de overlays
547	cmMap_overlaysInMap['polyline']= new Array(),cmMap_infoWindowInMap['polyline']= new Array();
548	cmMap_overlaysInMap['polygon']= new Array(),cmMap_infoWindowInMap['polygon']= new Array();
549	//cmMap_overlaysInMap['rectangule']= new Array(),cmMap_infoWindowInMap['rectangule']= new Array();
550	//cmMap_overlaysInMap['circle']= new Array(),cmMap_infoWindowInMap['circle']= new Array();
551	//esto es para que las rutas puedan tener infoWindow
552	cmMap_overlaysInMap['route']= new Array(),cmMap_infoWindowInMap['route']= new Array();
553	//el array cmMap_overlaysInMap tiene los siguientes campos
554	////cmMap_overlaysInMap[typeofOverlay][i].overlay
555	////cmMap_overlaysInMap[typeofOverlay][i].name
556	////cmMap_overlaysInMap[typeofOverlay][i].description
557	////cmMap_overlaysInMap[typeofOverlay][i].url
558	////cmMap_overlaysInMap[typeofOverlay][i].styleId
559	////cmMap_overlaysInMap[typeofOverlay][i].visible
560	////cmMap_overlaysInMap[typeofOverlay][i].clickForRouteFromHere
561	////cmMap_overlaysInMap[typeofOverlay][i].clickForRouteToHere
562	//el array de cmMap_infoWindowInMap tiene los siguientes campos
563	////cmMap_infoWindowInMap[typeofOverlay][i].infoWindow
564	
565	//para guardar los marcadores por categorias
566	var cmMap_MarkersInMapByCategory={};
567	
568	var cmMap_newOverlayLatLng="";
569
570	/*para las distintas imagenes de  los marcadores*/
571	var cmMap_markerImages = new Array(), cmMap_markerImagesLength = 0, cmMap_defaultIdImgMarker = "img_0", cmMap_defaultIdImgMarkerPrev = "
571img_0";
572	//el array cmMap_markerImages tiene los siguientes campos
573	////cmMap_markerImages[i].icon
574	////cmMap_markerImages[i].shadow
575	////cmMap_markerImages[i].cluster
576	////cmMap_markerImages[i].idImg
577	////cmMap_markerImages[i].markerIcon
578
579	//para los distintos colores que se pueden utilizar
580	var cmMap_overlayColors = new Array(), cmMap_overlayColorsLength = 0, cmMap_defaultIdColor = "color_0", cmMap_defaultIdColorPrev = "color_0";
581	//el array cmMap_overlayColors tiene los siguientes campos
582	////cmMap_overlayColors[i].idColor
583	////cmMap_overlayColors[i].strokeC
584	////cmMap_overlayColors[i].fillC
585	
586	//para cargar los controlares de dibujar diferentes overlays
587	var cmMap_drawingManager;
588	//para cargar los controladores propios para proxia
589	var cmMap_ownDrawingManager;
590	var cmMap_ownDrawingButtons={};
591	var cmMap_drawingMode='';
592	var markerDisabledControl;
593	var cmMap_clearButton;
594	
595	//banderas para indicar diferentes situaciones
596	var cmMap_clickNullButton=true;
597	var cmMap_changeRouteByDrag=true;
598	
599	//para guardar los estilos cargados desde un kml
600	var cmMap_styleKmlArray={};
601	
602	//variables para guardar las diferentes partes de un kml (para el modo editable tipo localizacion)
603	var kmlStyle='';
604	var kmlStyleUrl='';
605	var kmlCoordLat='';
606	var kmlCoordLng='';
607	var kmlPoint='';
608
609    /**
610     * Función que inicializa el mapa
611     * @param datosMapa
612     * @memberOf MapsApi
613     */
614	googleMapObject.cmMap_initialize = function(datosMapa) {
615
616		// Si tenemos alguna funcion personalizada a nivel de proyecto que quiera
617		// realizar alguna terea alternativa justo antes de inicializar el mapa, la llamamos...
618		if(typeof(cmMap_customPreInit) == 'function') {
619			cmMap_customPreInit(googleMapObject, datosMapa);
620		}
621
622		googleMapObject.cmMap_container=datosMapa.mapContainerToLoad;
623		cmMap_controls=$("div.cmMap_controls",googleMapObject.cmMap_container);
624		cmMap_directions=$("div.cmMap_directions",googleMapObject.cmMap_container);
625		if(cmMap_directions.length == 0) {
626			// Intentamos obtenerlo a través del mapa actual y buscamos un sibling que sea ese tipo.
627			actualmap = googleMapObject.cmMap_container.parents('div.cmMap_actualMap');
628			if(actualmap.length > 0) {
629				_directions  = actualmap.siblings('div.cmMap_directions');
630				if(_directions.length > 0) {
631					cmMap_directions = _directions;
632				}
633			}
634		}
635		cmMap_map=$("div.cmMap_googleMaps",googleMapObject.cmMap_container);
636
637		var urlKmlToLoad=datosMapa.kmlToLoad;
638		var zoomToSet=datosMapa.zoomToSet;
639		var latCoordToSet=datosMapa.latCoordToSet;
640		var lngCoordToSet=datosMapa.lngCoordToSet;
641		
642		//si se recibe zoom, y coordenadas se carga, sino se coge los parametros por defecto del proyecto
643		if(zoomToSet!='')googleMapObject.cmMap_zoom=zoomToSet;
644		if(latCoordToSet!='')googleMapObject.cmMap_LatCoord=latCoordToSet;
645		if(lngCoordToSet!='')googleMapObject.cmMap_LngCoord=lngCoordToSet;
646		
647		cmMap_directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
648		
649		//Creamos el mapa
650		googleMapObject.cmMap = new google.maps.Map(cmMap_map.get(0),myOptions);
651		//si el tipo por defecto de los mapas no es roadmap, se pone el adecuado
652		if(googleMapObject.cmMap_mapTypeId!='ROADMAP')
653			googleMapObject.cmMap.setMapTypeId(googleMapObject.cmMap_mapTypeId);
654
655		// Insertamos control custom para el zoom
656		var zoomControlDiv = $('<div class="control-zoom"></div>');
657		var zoomControl = new cmMap_customZoom(zoomControlDiv, googleMapObject.cmMap);
658		googleMapObject.cmMap.controls[google.maps.ControlPosition.RIGHT_TOP].push(zoomControlDiv[0]);
659		 
660		//Insertamos control custom para el tipo de mapa
661		var typeControlDiv =  $('<div class="control-type"></div>');
662		var typeControl = new cmMap_customType(typeControlDiv, googleMapObject.cmMap);
663		googleMapObject.cmMap.controls[google.maps.ControlPosition.TOP_LEFT].push(typeControlDiv[0]);
664
665		// Si tenemos alguna funcion personalizada a nivel de proyecto que quiera
666		// realizar alguna terea alternativa una vez haya cargado el mapa, la llamamos...
667		if(typeof(cmMap_customInit) == 'function') {
668			cmMap_customInit(googleMapObject, datosMapa);
669		}
670
671		// Si tenemos un buscador asociado al mapa adjuntamos los eventos correspondientes para
672		// que se realice la busqueda via ajax/json (solo si no estamos en modo wizard)
673		if(!googleMapObject.cmMap_editableMode){
674			var searchFormContainer = $("div.cmMap_searchForm", googleMapObject.cmMap_container.parent());
675			if(searchFormContainer.length > 0) {
676				loadScript({ url: cmMap_rootWeb+'/javaScript/markerwithlabel.js' });
677				googleMapObject.cmMap_searchForm = $("form:not(.print-form)", searchFormContainer);
678				googleMapObject.cmMap_searchForm.unbind().bind("submit", function() {
679					googleMapObject.cmMap_doSearch($(this),true);
680					return false;
681				});
682
683				var _isContent = (googleMapObject.cmMap_searchForm.data('type') == 'content');
684				var _contentName = '';
685
686				if(_isContent) {
687					_contentName = $('input[type="hidden"][name="content"]',googleMapObject.cmMap_searchForm).val();
688				}
689
690				// Si existe botón de mostrar lista, hacemos que salgan los resultados actuales
691				// paginados dentro de un dialogo de bootstrap
692				var $btnShowList = $(".btn-showlist", googleMapObject.cmMap_searchForm);
693				if($btnShowList.length > 0) {
694					$btnShowList.unbind().bind("click", function(e) {
695						e.preventDefault();
696
697						var $btn = $(this);
698
699						var _url = cmMap_rootWeb+'/cm/'+cmMap_currentWeb+'/maps-action';
700						var _params = 'json=true&order=2&'+googleMapObject.cmMap_searchForm.serialize();
701						var _initialPosition = ($btnShowList.data("position"))?$btnShowList.data("position"):0;
702						var _initialNShow = ($btnShowList.data("nshow"))?$btnShowList.data("nshow"):50;
703						var $modalDialog = googleMapObject.cmMap_initResultsModalDialog(_isContent, _contentName);
704						$("div.modal-body", $modalDialog).html('<div class="spinner"><span class="fa fa-4x fa-refresh fa-spin"></span></div>');
705
706						$modalDialog.on("hidden.bs.modal", function() {
707							onLightboxHidden($(this), $btn);
708							$(this).removeData("bs.modal").remove();
709						});
710
711						$modalDialog.on('shown.bs.modal', function() {
712							onLightboxShown($(this));
713							afterShowModalDialog($(this));
714						});
715
716						$modalDialog.modal('show');
717
718						$.ajax({
719							dataType: "json",
720							url: _url,
721							data: _params+'&position.mappoints='+_initialPosition+'&nshow.mappoints='+_initialNShow,
722							type: 'GET',
723							success: function(data){
724
725								if(data != null) {
726									googleMapObject.cmMap_loadResultsModalDialog($modalDialog, data, _url, _params);
727								}
728							}
729						});
730
731					});
732				}
733
734				// Si existe botón de imprimir lista, hacemos que salgan los resultados actuales
735				// paginados dentro de un iframe que posteriormente imprimiremos
736				var $btnPrintList = $(".btn-printlist", googleMapObject.cmMap_searchForm);
737				if($btnPrintList.length > 0) {
738					$btnPrintList.unbind().bind("click", function(e) {
739						e.preventDefault();
740
741						var $btn = $(this);
742
743						var _url = cmMap_rootWeb+'/cm/'+cmMap_currentWeb+'/maps-action';
744						var _params  = 'json=print&order=2&'+googleMapObject.cmMap_searchForm.serialize();
745							_params += '&position.mappoints=0';
746							_params += '&nshow.mappoints=1000000'; // Lo suyo seria poner -1
747
748						var $iframe = $("#iframePrintList");
749						if($iframe.length == 0) {
750							$iframe = $('<iframe id="iframePrintList" class="sr-only" aria-atomic="true" aria-live="assertive" src="about:blank"></iframe>');
751							$("body").append($iframe);
752						}
753
754						var $waitingModal = $("#waitingModal");
755						if($waitingModal.length == 0) {
756							$waitingModal = $(' \
757								<div class="modal fade" id="waitingModal" tabindex="-1" role="dialog" aria-labelledby="waitingLabel" aria-hidden="true" data-backdrop="static" data-keyboard="false"> \
758									<div class="modal-dialog"> \
759										<div class="modal-content"> \
760											<div class="modal-header"> \
761												<h1 class="modal-title h4" id="waitingLabel">'+resolveMessageinGmaps('{preparingImpression}')+'</h1> \
762											</div> \
763											<div class="modal-body"> \
764												<div class="progress"> \
765													<div class="progress-bar progress-bar-warning progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"></div> \
766												</div> \
767											</div> \
768										</div> \
769									</div> \
770								</div>');
771							$("body").append($waitingModal);
772						}
773
774						$waitingModal.on("hidden.bs.modal", function() {
775							onLightboxHidden($(this), $btn);
776							$(this).removeData("bs.modal").remove();
777						});
778
779						$waitingModal.on('shown.bs.modal', function() {
780							onLightboxShown($(this));
781							afterShowModalDialog($(this));
782						});
783
784						$waitingModal.modal("show");
785
786						$iframe.attr("src", _url+'?'+_params);
787
788					});
789				}
790
791			}
792		}
793
794        /**
795		 * @memberOf MapsApi
796         */
797		google.maps.event.addListenerOnce(googleMapObject.cmMap, 'idle', function() {
798
799			//Accesibilidad: Añadimos título adecuado para el marco iframe
800			$('.cmMap_googleMaps iframe').first().attr('title', 'Google Maps');
801		
802			// Si tenemos una funcion personalizada a nivel de proyecto que quiera
803			// procesar un kml alternativo antes de nuestro kml, la llamamos...
804			if(typeof(cmMap_customGetKml) == 'function') {
805				var cmMap_customKml = cmMap_customGetKml();
806				if(typeof(cmMap_customKml) == 'object') {
807					googleMapObject.cmMap_getKml(googleMapObject.cmMap_parserKml,cmMap_customKml,false);
808				}
809			}
810
811			googleMapObject.cmMap_getKml(googleMapObject.cmMap_parserKml,urlKmlToLoad,true);
812
813			// IE fix, a veces cuando tarda poco en cargar no representa bien el mapa
814			if($.browser.msie) {
815				// Le indicamos al mapa que ha sido cambiado de tamano
816				google.maps.event.trigger(googleMapObject.cmMap, 'resize');
817
818				// Volvemos a centrar y establecer el zoom
819				googleMapObject.cmMap_setCenterAndZoom();
820			}
821
822			// Flag que nos indica si ya ha cargado el mapa o no.
823			// En este punto ya deberiamos tener todo cargado.
824			googleMapObject.isLoaded = true;
825
826			// Si tenemos alguna funcion personalizada a nivel de proyecto que quiera
827			// realizar alguna terea alternativa justo al acabar de inicializar el mapa, la llamamos...
828			if(typeof(cmMap_customPostInit) == 'function') {
829				cmMap_customPostInit(googleMapObject);
830			}
831
832			// Cargamos los datos por defecto del mapa, si los tiene.
833			if(googleMapObject.cmMap_searchForm != null && googleMapObject.cmMap_searchForm.data('autoload') == "autoload") {
834				googleMapObject.cmMap_doSearch(googleMapObject.cmMap_searchForm,false);
835			}
836
837		});
838
839		/**
840		 * Modificamos los controles del mapa para hacerlos accesibles
841		 * @memberOf MapsApi
842         */
843		google.maps.event.addListenerOnce(googleMapObject.cmMap, 'tilesloaded', function(){
844			// Capa Google Maps
845			let $googleMaps = $('.cmMap_googleMaps');
846
847			// No hay evento para cuando los controles hayan cargado. 
848			// Y el último evento disponible (el de cargar las tiles), se lanza antes de eso.
849			// Asi que vamos comprobando si han cargado o no.
850			var controlsInterval = setInterval(function(){
851				// Enlace de reporte de errores
852				let $link = $('.gm-style-cc:last-child a', $googleMaps);
853				// Tabla de controles por teclado
854				let $table = $('.LGLeeN-keyboard-shortcuts-view table', $googleMaps);
855
856				if($link.length > 0 && $table.length > 0){
857					// Accesibilidad: Enlace reportar errores de Google Maps con texto significativo
858					let $img = $('img', $link);
859					if($img.length > 0){
860						$img.attr('alt', $link.attr('title'));
861					}
862
863					// Accesibilidad: Marcamos los encabezados en las tablas de Google Maps
864					$table.prepend(`<thead><tr><th>${_googleMapKeyboardIcon}</th><th>${_googleMapKeyboardIconDescription}</th></tr></thead>`);
865
866					clearInterval(controlsInterval);
867				}
868			}, 500);
869		});
870		
871		if(googleMapObject.cmMap_editableMode){
872			if(googleMapObject.cmMap_typeParam=='location'){
873				//Creamos un panel para mostrar como desahbilitado el marker del drawing manager
874				var markerDisabledControlContainer = document.createElement('DIV');
875				markerDisabledControlContainer.style.margin='0 0 0 -6px';
876				var markerDisControl = new cmMap_markerDisControl(markerDisabledControlContainer);
877	
878				markerDisabledControlContainer.index = 1;
879				googleMapObject.cmMap.controls[google.maps.ControlPosition.TOP_LEFT].push(markerDisabledControlContainer);
880			}
881			
882			//para que nos devuelva en coordenadas una dirección
883			cmMap_geocoder = new google.maps.Geocoder();
884			// Creamos una zona para poner controles propios.
885			cmMap_ownDrawingManager = document.createElement('DIV');
886			cmMap_ownDrawingManager.style.margin='0 0 0 -6px';
887			var newPanelControl = new cmMap_ownDrawingPanelControl(cmMap_ownDrawingManager);
888		
889			cmMap_ownDrawingManager.index = 100;
890			googleMapObject.cmMap.controls[google.maps.ControlPosition.TOP_LEFT].push(cmMap_ownDrawingManager);
891			
892			var drawingModesToSet=(googleMapObject.cmMap_typeParam=='location')?[google.maps.drawing.OverlayType.MARKER]:[google.maps.drawing.OverlayType.MARKER, google.maps.drawing.OverlayType.POLYGON,google.maps.drawing.OverlayType.POLYLINE]
893			//creamos controles para dibujar areas, marcadores...
894			cmMap_drawingManager = new google.maps.drawing.DrawingManager({
895				drawingControlOptions: {
896					drawingModes: drawingModesToSet
897				},
898				markerOptions: cmMap_markerOptions,
899				polylineOptions:{editable:googleMapObject.cmMap_editableMode,strokeColor:googleMapObject.cmMap_defaultStyleOverlay['strokeColor'],strokeOpacity:googleMapObject.cmMap_defaultStyleOverlay['strokeOpacity'],strokeWeight:googleMapObject.cmMap_defaultStyleOverlay['strokeWeight']},
900				polygonOptions:{editable:googleMapObject.cmMap_editableMode,strokeColor:googleMapObject.cmMap_defaultStyleOverlay['strokeColor'],strokeOpacity:googleMapObject.cmMap_defaultStyleOverlay['strokeOpacity'],strokeWeight:googleMapObject.cmMap_defaultStyleOverlay['strokeWeight'],fillColor:googleMapObject.cmMap_defaultStyleOverlay['fillColor'],fillOpacity:googleMapObject.cmMap_defaultStyleOverlay['fillOpacity']}
901			});
902			cmMap_drawingManager.setMap(googleMapObject.cmMap);
903		}
904		
905		//asignas listener en diferentes eventos en el mapa
906		cmMap_initializeEvents();
907	}
908
909    /**
910     * Función que prepara la llamada JSON al servidor
911     * @param searchForm - Formulario
912     * @param useCenter
913     * @memberOf MapsApi
914     */
915	googleMapObject.cmMap_doSearch = function(searchForm, useCenter) {
916
917		if(!googleMapObject.isLoaded) return;
918
919		// Contemplamos la posibilidad de anadir opciones personalizadas antes de realizar una busqueda JSON
920		if(typeof(cmMap_myCustomBeforeGetJSON) == 'function') {
921			cmMap_myCustomBeforeGetJSON(googleMapObject,searchForm);
922		}
923
924		var bounds = googleMapObject.cmMap.getBounds();
925		var ne = bounds.getNorthEast();
926		var sw = bounds.getSouthWest();
927
928		var params = googleMapObject.cmMap_serializeAndEncode(searchForm);
929
930		// Si no tenemos parametros seleccionados limpiamos el mapa de marcadores y no hacemos mas
931		if(params == '') {
932			googleMapObject.cmMap_clearMarkersJSON();
933			return;
934		}
935
936		params += '&minLat=' + ne.lat();
937		params += '&minLon=' + ne.lng();
938		params += '&maxLat=' + sw.lat();
939		params += '&maxLon=' + sw.lng();
940		params += '&zoom='   + googleMapObject.cmMap.zoom;
941
942		if(cmMap_useUrlHash && !googleMapObject.cmMap_editableMode && !wizardMode && !$("body").hasClass("cmWizardEditMode")) {
943
944			if(!googleMapObject.isAjaxLoaded) {
945				// Si la pagina no tenia un hash, usamos nosotros el hash para almacenar los datos del mapa para su persistencia
946				googleMapObject.pageHasPreviousHash = location.hash !== '' && location.hash.indexOf('#ancestorContent') == -1;
947				if(!googleMapObject.pageHasPreviousHash) {
948					var hashParams = googleMapObject.cmMap_deserializeUrlHash(params);
949					if(hashParams != '') {
950						params = hashParams;
951						var objParams = googleMapObject.cmMap_getUrlHashObject(params);
952						var getVal = googleMapObject.cmMap_getObjectValue;
953
954						// Establecemos los bordes de pantalla para centrar el mapa
955						if(getVal(objParams,"minLat") && getVal(objParams,"minLon") && getVal(objParams,"maxLat") && getVal(objParams,"maxLon")) {
956							var bounds = new google.maps.LatLngBounds();
957							bounds.extend(new google.maps.LatLng(getVal(objParams,"minLat"),getVal(objParams,"minLon")));
958							bounds.extend(new google.maps.LatLng(getVal(objParams,"maxLat"),getVal(objParams,"maxLon")));
959							googleMapObject.cmMap.fitBounds(bounds);
960						}
961
962						// Establecemos el zoom
963						if(getVal(objParams,"zoom")) {
964							googleMapObject.cmMap.setZoom(parseInt(getVal(objParams,"zoom"),10));
965						}
966
967						// Establecemos los valores del formularios previamente seleccionados
968						var $searchForm = $(googleMapObject.cmMap_searchForm);
969						for(var i = 0; i < objParams.length; i++) {
970							var $field = $("[name='"+objParams[i].name+"']", $searchForm);
971							if($field.length > 0) {
972								var value = objParams[i].value;
973								if(value && value != '') {
974									if($field.is("[type='checkbox']") || $field.is("[type='radio']")) {
975										$field.filter("[value='"+value+"']").prop("checked", true);
976									} else {
977										$field.val(value);
978										if($field.data("location") && typeof($field.proxiaLocation) == 'function') {
979											$field.proxiaLocation("reset");
980										}
981									}
982								}
983							}
984						}
985					}
986				}
987				googleMapObject.isAjaxLoaded = true;
988			} else {
989				if(!googleMapObject.pageHasPreviousHash) {
990					googleMapObject.cmMap_pushState(googleMapObject.cmMap_serializeUrlHash(params));
991				}
992			}
993		}
994
995		googleMapObject.cmMap_getJSON(null,cmMap_rootWeb+'/cm/'+cmMap_currentWeb+'/maps?'+params,false,searchForm,useCenter);
996	}
997
998    /**
999     * Función que obtiene el objeto bounds
1000     * @memberOf MapsApi
1001     */
1002	googleMapObject.cmMap_fitBounds = function() {
1003		googleMapObject.cmMap.fitBounds(cmMap_bounds);
1004	}
1005
1006    /**
1007     * Función que centra en el mapa y aplica el zoom
1008     * @memberOf MapsApi
1009     */
1010	googleMapObject.cmMap_setCenterAndZoom = function() {
1011
1012		// Centramos el mapa una vez cargados todos los puntos
1013		if(!cmMap_bounds.isEmpty() && !cmMap_customCenterAndZoom) {
1014			googleMapObject.cmMap.fitBounds(cmMap_bounds);
1015			var cmMap_elementsCount = cmMap_overlaysInMap['markerNotInRoute'].length + cmMap_overlaysInMap['markerInRoute'].length + cmMap_overlaysInMap['polyline'].length + cmMap_overlaysInMap['polygon'].length + googleMapObject.cmMap_jsonMarkers.length + googleMapObject.cmMap_jsonPolys.length;
1016			if(cmMap_elementsCount <= 1)
1017				googleMapObject.cmMap.setZoom(googleMapObject.cmMap_zoom);
1018		}
1019		else {
1020			//si no tenemos elementos en el mapa lo posicionamos en las coordenadas por defecto con el nivel de zoom por defecto
1021			googleMapObject.cmMap.setCenter(new google.maps.LatLng(googleMapObject.cmMap_LatCoord,googleMapObject.cmMap_LngCoord));
1022			googleMapObject.cmMap.setZoom(googleMapObject.cmMap_zoom);
1023		}
1024
1025		// Actualizamos las coordenadas de centrado del mapa
1026		if(googleMapObject.cmMap_editableMode && googleMapObject.cmMap_typeParam!='location' && $("#cmMap_zoomCenter").length > 0){
1027			var _coords = googleMapObject.cmMap.getCenter();
1028			var _lat = parseFloat(_coords.lat()).toFixed(6);
1029			var _lng = parseFloat(_coords.lng()).toFixed(6);
1030			$("#cmMap_zoomCenter").text(_lat.toString() + ',' + _lng.toString());
1031		}
1032	}
1033
1034    /**
1035     * Función que obtiene el kml con la información del mapa
1036     * @param _parserKml - KML
1037     * @param {string} url - Url
1038     * @param _saveOverlay
1039     * @memberOf MapsApi
1040     */
1041	googleMapObject.cmMap_getKml = function(_parserKml,url,_saveOverlay) {
1042
1043		if(_parserKml == null) _parserKml = googleMapObject.cmMap_parserKml;
1044
1045		// Realizamos la peticion ajax si es necesario
1046		if(typeof(url) == 'string') {
1047			$.ajax({
1048				type: 'GET',
1049				url: url,
1050				dataType: $.browser.msie ? 'text' : 'xml',
1051				success: function(kml) {
1052					if(typeof(kml) == "string") kml = $.parseXML(kml);
1053					_parserKml(kml,_saveOverlay);
1054				}
1055			});
1056		}else{
1057			_parserKml(url,_saveOverlay);
1058		}
1059	}
1060
1061    /**
1062     * Función que procesa los marcadores, rutas, lineas, polígonos...de un kml
1063     * @param kml - KML
1064     * @param _saveOverlay
1065     * @memberOf MapsApi
1066     */
1067	googleMapObject.cmMap_parserKml=function(kml,_saveOverlay) {
1068		if(kml != null) {
1069			var kmlResp = kml.getElementsByTagName("Document"), i, j;
1070			var isFirstPlacemark = true;
1071			if(kmlResp.length > 0) {
1072				var _nodes = kmlResp[0].childNodes;
1073
1074				//valores por defecto
1075				cmMap_styleKmlArray['default']=new Array();
1076				cmMap_styleKmlArray['default'].idImgMarker=cmMap_defaultIdImgMarker;
1077				cmMap_styleKmlArray['default'].idColorOverlay=cmMap_defaultIdColor;
1078
1079				for(i = 0; i < _nodes.length; i++) {
1080					var _node = _nodes[i];
1081					switch(_node.nodeName) {
1082						case 'Style':
1083							cmMap_getStyleFromKml(_node);
1084							break;
1085						case 'ExtendedData':
1086							//si tenemos un ExtendedData en el raiz comprobamos si tenemos que aplicar un nivel de zoom y centrado personalizados para el tipo de parametro kml
1087							var _placemarkData = _node;
1088							if(_placemarkData.childNodes.length > 0) _placemarkData = _placemarkData.getElementsByTagName("Data");
1089							if(_placemarkData.length > 0) {
1090								for(var d = 0; d < _placemarkData.length; d++) {
1091									if(_placemarkData[d].getAttribute('name')) {
1092										switch(_placemarkData[d].getAttribute('name')) {
1093											case 'zoomLevel':
1094												var _placemarkValue = _placemarkData[d].getElementsByTagName("value");
1095												if(_placemarkValue.length > 0) {
1096													googleMapObject.cmMap_zoom = parseInt(_placemarkValue[0].childNodes[0].nodeValue, 10);
1097												}
1098												break;
1099											case 'mapTypeId':
1100												var _placemarkValue = _placemarkData[d].getElementsByTagName("value");
1101												if(_placemarkValue.length > 0) {
1102													googleMapObject.cmMap_mapTypeId=_placemarkValue[0].childNodes[0].nodeValue;
1103												}
1104												break;
1105											case 'centerCoords':
1106												var _placemarkValue = _placemarkData[d].getElementsByTagName("value");
1107												if(_placemarkValue.length > 0) {
1108
1109													// Recogemos las coordenadas personalizadas
1110													var _coords = _placemarkValue[0].childNodes[0].nodeValue;
1111													_coords = _coords.split(',');
1112													googleMapObject.cmMap_LatCoord = parseFloat(_coords[0]);
1113													googleMapObject.cmMap_LngCoord = parseFloat(_coords[1]);
1114
1115													// Indicamos que coja nuestro zoom y coordenadas personalizadas
1116													cmMap_customCenterAndZoom = true;
1117
1118													// Mostramos los controles de zoom y coordenadas personalizadas
1119													if($("#cmMap_customZoomLevel").length > 0) {
1120														$("#cmMap_customZoomLevel").attr("checked","checked");
1121														$("#cmMap_zoomLevelSelect,div.cmMap_formFieldCenter").css("visibility","visible");
1122													}
1123												}
1124												break;
1125											case 'styleUrl':
1126												var _placemarkValue = _placemarkData[d].getElementsByTagName("value");
1127												if(_placemarkValue.length > 0) {
1128													googleMapObject.cmMap_icon = _placemarkValue[0].childNodes[0].nodeValue;
1129												}
1130												break;
1131										}
1132									}
1133								}
1134							}
1135							break;
1136						case 'Placemark':
1137							var _placemark = _node.childNodes, _subnode;
1138							var _overlayName, _overlayDescription, _overlayLink, _overlayStyle;
1139							var _point = null, _polygon = null, _lineString = null;
1140
1141							//si tenemos un primer placemark comprobamos si tenemos que aplicar un nivel de zoom personalizado para el tipo de parametro location
1142							if(isFirstPlacemark) {
1143								isFirstPlacemark = false;
1144								var cmMap_zoomPrev=googleMapObject.cmMap_zoom;
1145								var cmMap_mapTypeIdPrev=googleMapObject.cmMap_mapTypeId;
1146								var _placemarkData = _node.getElementsByTagName("ExtendedData");
1147								if(_placemarkData.length > 0) _placemarkData = _placemarkData[0].getElementsByTagName("Data");
1148								if(_placemarkData.length > 0) {
1149									for(var d = 0; d < _placemarkData.length; d++) {
1150										if(_placemarkData[d].getAttribute('name')) {
1151											switch(_placemarkData[d].getAttribute('name')){
1152												case 'zoomLevel':
1153													var _placemarkValue = _placemarkData[d].getElementsByTagName("value");
1154													if(_placemarkValue.length > 0 && _placemarkValue[0].childNodes.length > 0) {
1155														// Si el zoom devuelto es 0 usamos el de por defecto.
1156                                                        var _placemarkValueInt = parseInt(_placemarkValue[0].childNodes[0].nodeValue, 10);
1157                                                        if(_placemarkValueInt != 0){
1158                                                            googleMapObject.cmMap_zoom = _placemarkValueInt;
1159                                                        }
1160														// Mostramos los controles de zoom personalizadas
1161														if($("#cmMap_customZoomLevel").length > 0) {
1162															$("#cmMap_customZoomLevel").attr("checked","checked");
1163															$("#cmMap_zoomLevelSelect").css("visibility","visible");
1164														}
1165													}
1166													
1167												break;
1168												case 'mapTypeId':
1169													var _placemarkValue = _placemarkData[d].getElementsByTagName("value");
1170													if(_placemarkValue.length > 0 && _placemarkValue[0].childNodes.length > 0) {
1171														googleMapObject.cmMap_mapTypeId=_placemarkValue[0].childNodes[0].nodeValue;
1172													}
1173												break;
1174											}
1175										}
1176									}
1177								}
1178							}else{
1179								//si hay mas de un placemark, aunque en uno haya valores especificos no se aplican
1180								//suele pasar en el cuaderno de viaje donde se recopilan diferenres kml de tipo localizacion
1181								googleMapObject.cmMap_mapTypeId=cmMap_mapTypeIdPrev;
1182								googleMapObject.cmMap_zoom=cmMap_zoomPrev;
1183							}
1184
1185							for(j = 0; j < _placemark.length; j++) {
1186								_subnode = _placemark[j];
1187								switch(_subnode.nodeName) {
1188									case 'name':
1189										_overlayName = (_subnode.childNodes.length > 0)?_subnode.childNodes[0].nodeValue:'';
1190										break;
1191									case 'description':
1192										_overlayDescription = cmMap_getOverlayDescriptionValue(_subnode);
1193										break;
1194									case 'Link':
1195										_overlayLink = (_subnode.childNodes.length > 0)?_subnode.childNodes[0].nodeValue:'';
1196										break;
1197									case 'styleUrl':
1198										_overlayStyle = (_subnode.childNodes.length > 0 && _subnode.childNodes[0].nodeValue && _subnode.childNodes[0].nodeValue != '' && cmMap_removeSpaces(_subnode.childNodes[0].nodeValue)!='')?_subnode.childNodes[0].nodeValue.substring(1):'default';
1199										break;
1200									case 'Point':
1201										_point = _subnode;
1202										break;
1203									case 'Polygon':
1204										_polygon = _subnode;
1205										break;
1206									case 'LineString':
1207										_lineString = _subnode;
1208										break;
1209								}
1210							}
1211
1212							//si estamos en modo de edicion tipo location, solo pintamos marcador
1213							if(!(googleMapObject.cmMap_editableMode && googleMapObject.cmMap_typeParam=='location' && (_point == null || cmMap_contMarkerInMap>0))){
1214
1215								if(_point != null && _point.childNodes.length > 0) {
1216									/* marcador */
1217									cmMap_drawMarkerFromKml(_point,_overlayName,_overlayDescription,_overlayLink,_overlayStyle);
1218									//indicamos si estamos en modo edicion tipo localizacion que se ha alcanzado el maximo de marcadores (1)
1219									if(googleMapObject.cmMap_editableMode && googleMapObject.cmMap_typeParam=='location'){googleMapObject.cmMap_container.trigger('maxPointReach');}
1220								}
1221
1222								if(_polygon != null && _polygon.childNodes.length > 0) {
1223									/* poligono */
1224									cmMap_drawPolygonFromKml(_polygon,_overlayName,_overlayDescription,_overlayLink,_overlayStyle,_saveOverlay);
1225								}
1226
1227								if(_lineString != null && _lineString.childNodes.length > 0) {
1228									/* linea o ruta */
1229									var _coordinates = _lineString.getElementsByTagName("coordinates");
1230									if(_coordinates.length > 0) {
1231										var _overlayCoordsToCreate = cmMap_getCoordsFromKml(_coordinates[0],_saveOverlay);
1232										if(_overlayCoordsToCreate.length > 0) {
1233											//detectar si es una ruta o linea recta
1234											var _isRoute = false;
1235											var _extendedData = _node.getElementsByTagName("ExtendedData");
1236											if(_extendedData.length > 0) _extendedData = _extendedData[0].getElementsByTagName("Data");
1237											for(var d = 0; d < _extendedData.length; d++) {
1238												if(_extendedData[d].getAttribute('name') && _extendedData[d].getAttribute('name')=='_SnapToRoads') {
1239													_isRoute = true;
1240													break;
1241												}
1242											}
1243											/*ruta*/
1244											if(_isRoute){
1245												cmMap_drawRouteFromKml(_overlayCoordsToCreate,_overlayName,_overlayDescription,_overlayLink);
1246											}else{
1247											/*linea*/
1248												cmMap_drawLineFromKml(_overlayCoordsToCreate,_overlayName,_overlayDescription,_overlayLink,_overlayStyle)
1249											}
1250										}
1251									}
1252								}
1253							}
1254
1255							break;
1256					}
1257				}
1258			}
1259		}
1260		googleMapObject.cmMap_overlayColors = cmMap_overlayColors;
1261		googleMapObject.cmMap_afterParsing();
1262	}
1263
1264
1265    /**
1266     * Función que obtiene el json con la información del mapa
1267     * @param {object} _parserJSON - JSON
1268     * @param {string} url - Url
1269     * @param _saveOverlay
1270     * @param searchForm - Formulario de búsqueda
1271     * @param useCenter
1272     * @memberOf MapsApi
1273     */
1274	googleMapObject.cmMap_getJSON=function(_parserJSON,url,_saveOverlay,searchForm,useCenter) {
1275
1276		if(_parserJSON == null) _parserJSON = googleMapObject.cmMap_parserJSON;
1277
1278		// Realizamos la peticion ajax si es necesario
1279		if(typeof(url) == 'string') {
1280			var aUrl = url.split('?');
1281			var ajaxUrl = aUrl[0];
1282			var ajaxParams = (aUrl.length > 1) ? aUrl[1] : '';
1283
1284			$.ajax({
1285				dataType: "json",
1286				url: ajaxUrl,
1287				data: ajaxParams,
1288				type: 'POST',
1289				success: function(data) {
1290					_parserJSON(data,_saveOverlay,searchForm,useCenter);
1291				}
1292			});
1293		}else{
1294			_parserJSON(url,_saveOverlay,searchForm,useCenter);
1295		}
1296	}
1297
1298    /**
1299     * Función que aplica los parámetros a la URL para recordar los ultimos parámetros buscados en el navegador
1300     * @param {string} path - Url
1301     * @memberOf MapsApi
1302     */
1303	googleMapObject.cmMap_pushState=function(path) {
1304
1305		if (typeof(window.history.replaceState) == 'function') {
1306			window.history.replaceState(null, path, path);
1307		} else {
1308			window.location.hash = path;
1309		}
1310	}
1311
1312    /**
1313     * Función que devuelve un array con los nombres de los parámetros de una URL
1314     * @param {string} params - Parámetros
1315     * @returns {Array} Array con los nombres de los parámetros
1316     * @memberOf MapsApi
1317     */
1318	googleMapObject.cmMap_getUrlHashNames=function(params) {
1319		var names  = [];
1320		var aParams = params.split('&');
1321
1322		for(var i = 0; i < aParams.length; i++) {
1323			var param = aParams[i];
1324			var parts = param.split("=");
1325			var name = parts.length > 0 ? parts[0] : '';
1326
1327			names.push(name);
1328		}
1329
1330		return names;
1331	}
1332
1333    /**
1334     * Función que devuelve un array con los valores de los parámetros de una URL
1335     * @param {string} params - Parámetros
1336     * @returns {Array} Array con los valores de los parámetros
1337     * @memberOf MapsApi
1338     */
1339	googleMapObject.cmMap_getUrlHashValues=function(params) {
1340		var values  = [];
1341		var aParams = params.split('&');
1342
1343		for(var i = 0; i < aParams.length; i++) {
1344			var param = aParams[i];
1345			var parts = param.split("=");
1346			var name = parts.length > 0 ? parts[0] : '';
1347			var value = parts.length > 1 ? parts[1] : '';
1348
1349			values.push(value);
1350		}
1351
1352		return values;
1353	}
1354
1355    /**
1356     * Función que codifica los campos de formulario usando encodeURIComponent, jQuery no lo hace como queremos
1357     * @param searchForm
1358     * @memberOf MapsApi
1359     */
1360	googleMapObject.cmMap_serializeAndEncode=function(searchForm) {
1361		return $.map(searchForm.serializeArray(), function(val) {
1362			return [val.name, encodeURIComponent(val.value)].join('=');
1363		}).join('&');
1364	}
1365
1366    /**
1367     * Función que devuelve un objeto con los nombres de parametro y los valores de los parámetros de una URL
1368     * @param {string} params - Parámetros
1369     * @returns {Array} Array con los valores de los parámetros y sus valores
1370     * @memberOf MapsApi
1371     */
1372	googleMapObject.cmMap_getUrlHashObject=function(params) {
1373		var obj  = [];
1374		var aParams = params.split('&');
1375
1376		for(var i = 0; i < aParams.length; i++) {
1377			var param = aParams[i];
1378			var parts = param.split("=");
1379			var name = parts.length > 0 ? parts[0] : '';
1380			var value = parts.length > 1 ? decodeURIComponent(parts[1]) : '';
1381
1382			var pair = {};
1383			pair.name = name;
1384			pair.value = value;
1385			obj.push(pair);
1386		}
1387
1388		return obj;
1389	}
1390
1391    /**
1392     * @param obj
1393     * @param name
1394     * @memberOf MapsApi
1395     */
1396	googleMapObject.cmMap_getObjectValue=function(obj, name) {
1397		for(var i = 0; i < obj.length; i++) {
1398			if(name == obj[i].name) return obj[i].value;
1399		}
1400	}
1401
1402    /**
1403     * Función que convierte los parámetros de la URL a una versión corta
1404     * @param {string} params - Parámetros
1405     * @returns {string}
1406     * @memberOf MapsApi
1407     */
1408	googleMapObject.cmMap_serializeUrlHash=function(params) {
1409
1410		var names = googleMapObject.cmMap_getUrlHashNames(params);
1411		var values = googleMapObject.cmMap_getUrlHashValues(params);
1412		var result = [];
1413		for(var i = 0; i < names.length; i++) {
1414			result.push(names[i]+'='+values[i]);
1415		}
1416		result = result.join('!');
1417
1418		return result.length > 0 ? '#'+result : '';
1419	}
1420
1421
1422    /**
1423     * Función que convierte los parámetros de la URL a una versión larga
1424     * @param {string} params - Parámetros
1425     * @returns {string}
1426     * @memberOf MapsApi
1427     */
1428	googleMapObject.cmMap_deserializeUrlHash=function(params) {
1429
1430		var hash = location.hash;
1431
1432		if(!params || params == '' || params.length == 0 || hash == '') return '';
1433
1434		if(hash.indexOf('#') != -1) {
1435			hash = hash.substring(1);
1436		}
1437
1438		var result = '';
1439		var url = [];
1440		var hashes = hash.split('!');
1441		if(hashes.length > 0) {
1442			for(var i = 0; i < hashes.length; i++) {
1443				url.push(hashes[i]);
1444			}
1445			result = url.join('&');
1446		}
1447
1448		return result;
1449	}
1450
1451    /**
1452     * Función que procesa los marcadores de la llamada json
1453     * @param {object} data - Datos a tratar
1454     * @param _saveOverlay
1455     * @param searchForm - Formulario de búsqueda
1456     * @param useCenter
1457     * @memberOf MapsApi
1458     */
1459	googleMapObject.cmMap_parserJSON=function(data,_saveOverlay,searchForm,useCenter) {
1460		if(data != null) {
1461
1462			googleMapObject.cmMap_clearMarkersJSON();
1463
1464			// Tenemos que centrar el mapa en ese punto concreto
1465			if(useCenter && data.centrum) {
1466				googleMapObject.cmMap.setCenter(data.centrum);
1467			}
1468
1469			if(!data.clusters && !data.polys) return;
1470
1471			$.each(data.polys, function(key,val) {
1472
1473				var cmMap_overlayColors = googleMapObject.cmMap_overlayColors;
1474				var _idColorForOverlay = cmMap_defaultIdColor;
1475
1476				// Tenemos que crear el poligono, inicialmente solo pintamos el area
1477				if(val.polyType == 'AREA') {
1478					if(val.styleRef) {
1479						var _style = cmMap_overlayColors[val.styleRef.replace('#polygon_','')];
1480						if(_style && _style.idColor!='') _idColorForOverlay = _style.idColor;
1481					}
1482
1483					googleMapObject.cmMap_jsonPolys[key] = new google.maps.Polygon({
1484						paths: val.points,
1485						center: {lat: val.points[0].lat, lng: val.points[0].lng},
1486						title: val.title,
1487						content: val.content,
1488						editable: false,
1489						strokeColor: cmMap_overlayColors[_idColorForOverlay].strokeC,
1490						strokeOpacity: cmMap_overlayColors[_idColorForOverlay].strokeO,
1491						strokeWeight: cmMap_overlayColors[_idColorForOverlay].strokeW,
1492						fillColor: cmMap_overlayColors[_idColorForOverlay].fillC,
1493						fillOpacity: cmMap_overlayColors[_idColorForOverlay].fillO
1494					});
1495
1496					cmMap_bounds.extend(new google.maps.LatLng(val.points[0].lat,val.points[0].lng));
1497				
1498					cmMap_initPolyTooltip(googleMapObject.cmMap_jsonPolys[key]);
1499
1500				} else if(val.polyType == 'LINE') {
1501					if(val.styleRef) {
1502						var _style = cmMap_overlayColors[val.styleRef.replace('#polyline_','')];
1503						if(_style && _style.idColor!='') _idColorForOverlay = _style.idColor;
1504					}
1505
1506					googleMapObject.cmMap_jsonPolys[key] = new google.maps.Polyline({
1507						path: val.points,
1508						center: {lat: val.points[0].lat, lng: val.points[0].lng},
1509						title: val.title,
1510						content: val.content,
1511						editable: false,
1512						strokeColor: cmMap_overlayColors[_idColorForOverlay].strokeC,
1513						strokeOpacity: cmMap_overlayColors[_idColorForOverlay].strokeO,
1514						strokeWeight: cmMap_overlayColors[_idColorForOverlay].strokeW
1515					});
1516					
1517					cmMap_bounds.extend(new google.maps.LatLng(val.points[0].lat,val.points[0].lng));
1518
1519					cmMap_initPolyTooltip(googleMapObject.cmMap_jsonPolys[key]);
1520
1521				} else if(val.polyType == 'SET_OF_POINTS') {
1522
1523					var iconIndex = val.iconRef.substr(1);
1524
1525					if(val.iconRef && cmMap_markerImages[iconIndex]){
1526						val.icon = cmMap_markerImages[iconIndex].icon;
1527						val.shadow = cmMap_markerImages[iconIndex].shadow;
1528					}else{
1529						val.icon = googleMapObject.cmMap_defaultImageMarker;
1530						val.shadow = googleMapObject.cmMap_defaultShadowMarker;
1531					}
1532					
1533					if(val.points.length > 0) {
1534						googleMapObject.cmMap_jsonPolys[key] = {};
1535						googleMapObject.cmMap_jsonPolys[key].points = new Array();
1536						for (var i = 0; i < val.points.length; i++) {
1537							var point = val.points[i];
1538							var marker = val;
1539							marker.position = point;
1540							marker.center = {lat: point.lat, lng: point.lng};
1541
1542							cmMap_bounds.extend(new google.maps.LatLng(point.lat,point.lng));
1543							googleMapObject.cmMap_jsonPolys[key].points[i] = new google.maps.Marker(marker);
1544						}
1545					}
1546
1547				} else if(val.polyType == 'ROAD') {
1548
1549					var waypts = [];
1550					var start = new google.maps.LatLng(val.points[0].lat, val.points[0].lng);
1551					var end = new google.maps.LatLng(val.points[val.points.length-1].lat, val.points[val.points.length-1].lng);
1552					
1553					// Se necesitan al menos dos puntos para pintar una ruta
1554					if(val.points.length<2) return;
1555
1556					for (var i = 1; i < val.points.length - 1 && i <= 8; i++) {
1557						waypts.push({
1558							location:new google.maps.LatLng(val.points[i].lat, val.points[i].lng),
1559							stopover:true
1560						});
1561					}
1562
1563					var request = {
1564						origin:start,
1565						destination:end,
1566						waypoints: waypts,
1567						travelMode: google.maps.TravelMode.DRIVING,
1568						region: cmMap_region
1569					};
1570						
1571					googleMapObject.cmMap_jsonPolys[key] = new google.maps.DirectionsRenderer(rendererOptions);
1572					googleMapObject.cmMap_jsonPolys[key].markersInRoute = new Array();
1573
1574					for (var i = 0; i < val.points.length && i <= 10; i++) {
1575						googleMapObject.cmMap_jsonPolys[key].markersInRoute[i] = new google.maps.Marker($.extend(cmMap_markerOptionsInRoute, { position: val.points[i] }));
1576						googleMapObject.cmMap_jsonPolys[key].markersInRoute[i].setMap(googleMapObject.cmMap);
1577						cmMap_bounds.extend(new google.maps.LatLng(val.points[i].lat,val.points[i].lng));
1578					}
1579
1580					cmMap_directionsService.route(request, function(result, status) {
1581						if (status == google.maps.DirectionsStatus.OK) {
1582							
1583							googleMapObject.cmMap_jsonPolys[key].setDirections(result);
1584							googleMapObject.cmMap_jsonPolys[key].setMap(googleMapObject.cmMap);
1585						}
1586					});
1587
1588				} else {
1589					return; // Si no es de ninguno de los tipos soportados continuamos...
1590				}
1591
1592				if(val.polyType == 'SET_OF_POINTS' && googleMapObject.cmMap_jsonPolys[key].points) {
1593					for(var i = 0; i < googleMapObject.cmMap_jsonPolys[key].points.length; i++) {
1594						google.maps.event.addListener(googleMapObject.cmMap_jsonPolys[key].points[i], 'click', googleMapObject.cmMap_clickMarkerInfoWindow);
1595						googleMapObject.cmMap_jsonPolys[key].points[i].setMap(googleMapObject.cmMap);
1596					}
1597				} else {
1598					google.maps.event.addListener(googleMapObject.cmMap_jsonPolys[key], 'click', googleMapObject.cmMap_clickMarkerInfoWindow);
1599
1600					if(val.polyType != 'ROAD')
1601						googleMapObject.cmMap_jsonPolys[key].setMap(googleMapObject.cmMap);
1602				}
1603
1604			});
1605
1606			$.each( data.clusters, function( key, val ) {
1607
1608				if(val.clusterSize) {
1609
1610					var clusterIndex = val.iconRef.substr(1).replace('cluster','img');
1611					if(val.iconRef && cmMap_markerImages[clusterIndex]){
1612						val.cluster = cmMap_markerImages[clusterIndex].cluster;
1613					}else{
1614						val.cluster = googleMapObject.cmMap_defaultImageCluster;
1615					}
1616
1617					var labelClassName = "cluster-label";
1618					if(cmMap_markerImages[clusterIndex].baseClassName != '') {
1619						labelClassName += ' ' + cmMap_markerImages[clusterIndex].baseClassName;
1620					}
1621
1622					// Creamos el cluster...
1623					googleMapObject.cmMap_jsonMarkers[key] = new MarkerWithLabel($.extend(val, {
1624						draggable: false,
1625						raiseOnDrag: false,
1626						icon: val.cluster,
1627						map: googleMapObject.cmMap,
1628						labelContent: val.clusterSize.toString(),
1629						labelAnchor: val.cluster.anchor,
1630						labelClass: labelClassName
1631					}));
1632
1633					// Guardamos el unzoom en el cluster para utilizarlo dentro del 'click'...
1634					googleMapObject.cmMap_jsonMarkers[key].unzoom = val.unzoom;
1635
1636					// Al hacer click en el cluster...
1637					google.maps.event.addListener(googleMapObject.cmMap_jsonMarkers[key], 'click', function() {
1638
1639						// Si existe un infoWindow lo cerramos
1640						if(cmMap_oldInfoWindow) {
1641							cmMap_oldInfoWindow.close();
1642						}
1643
1644						// Centramos el cluster en el mapa y hacemos el unzoom
1645						if(this.unzoom.zoom > 0) {
1646							googleMapObject.cmMap.setCenter(this.unzoom.position);
1647							googleMapObject.cmMap.setZoom(this.unzoom.zoom);
1648						}
1649
1650					});
1651
1652				} else {
1653					var iconIndex = val.iconRef.substr(1);
1654
1655					if(val.iconRef && cmMap_markerImages[iconIndex]){
1656						val.icon = cmMap_markerImages[iconIndex].icon;
1657						val.shadow = cmMap_markerImages[iconIndex].shadow;
1658					}else{
1659						val.icon = googleMapObject.cmMap_defaultImageMarker;
1660						val.shadow = googleMapObject.cmMap_defaultShadowMarker;
1661					}
1662
1663					googleMapObject.cmMap_jsonMarkers[key] = new google.maps.Marker(val);
1664
1665					google.maps.event.addListener(googleMapObject.cmMap_jsonMarkers[key], 'click', function() {
1666
1667						var marker = this;
1668
1669						var urlInfoWindow  = cmMap_rootWeb+"/cm/"+cmMap_currentWeb+"/connector";
1670							urlInfoWindow += "?idContent="+marker.content.idContent;
1671							urlInfoWindow += "&alias="+marker.content.alias;
1672							urlInfoWindow += "&formatType="+cmMap_infoWindowTemplate;
1673							urlInfoWindow += "&locale="+cmMap_locale;
1674
1675						$.ajax({
1676							url: urlInfoWindow,
1677							success: function(htmlInfoWindow){
1678
1679								// Preparamos el contenido del infoWindow
1680								var contentInfoWindow = '<div class="infoWindowWrapper">';
1681									contentInfoWindow+= '	' + htmlInfoWindow;
1682									contentInfoWindow+= '	<div class="infoWindowUrl">';
1683									contentInfoWindow+= '		<a href="/'+marker.content.alias+'/'+cmMap_lang+'/'+marker.content.pathName+'" class="readMore">'+resolveMessageinGmaps('{readMore}')+'</a>';
1684									if(cmMap_howToArrive){
1685										contentInfoWindow+= '		&nbsp;|&nbsp; <a href="javascript:;" class="howToArrive">'+resolveMessageinGmaps('{directionsFromHere}')+'</a>';
1686									}
1687									contentInfoWindow+= '	</div>';
1688									contentInfoWindow+= '</div>';
1689								
1690								var $contentInfoWindow = $(contentInfoWindow);
1691
1692								// Borramos el anterior infoWindow, creamos y abrimos
1693								if(cmMap_oldInfoWindow) {
1694									cmMap_oldInfoWindow.close();
1695								}
1696								cmMap_oldInfoWindow = new google.maps.InfoWindow();
1697								if(cmMap_maxWidthInfoWindow != 'auto') {
1698									cmMap_oldInfoWindow.setOptions({ maxWidth: cmMap_maxWidthInfoWindow });
1699								}
1700								cmMap_oldInfoWindow.setContent($contentInfoWindow.get(0));
1701								cmMap_oldInfoWindow.open(googleMapObject.cmMap,marker);
1702
1703								// Asociamos el evento correspondiente al enlace 'Ruta desde aqui'
1704								if(cmMap_howToArrive){
1705									var _howToArrive = $("a.howToArrive", $contentInfoWindow);
1706									if(_howToArrive.length > 0) {
1707										_howToArrive.click(function() {
1708											googleMapObject.cmMap_howToArriveJSON(marker);
1709										});
1710									}
1711								}
1712
1713								// Si tenemos alguna funcion personalizada a nivel de proyecto que quiera
1714								// realizar alguna terea alternativa una vez abierto un infoWindow, la llamamos...
1715								if(typeof(cmMap_customAfterOpenInfoWindow) == 'function') {
1716									cmMap_customAfterOpenInfoWindow(googleMapObject, cmMap_oldInfoWindow, marker);
1717								}
1718
1719							}
1720						});
1721
1722					});
1723
1724					googleMapObject.cmMap_jsonMarkers[key].setMap(googleMapObject.cmMap);
1725				}
1726
1727			});
1728		}
1729
1730		// Contemplamos la posibilidad de anadir opciones personalizadas despues de realizar una busqueda JSON
1731		if(typeof(cmMap_myCustomAfterGetJSON) == 'function') {
1732			cmMap_myCustomAfterGetJSON(googleMapObject,searchForm);
1733		}
1734	}
1735
1736    /**
1737     * @memberOf MapsApi
1738     */
1739	googleMapObject.cmMap_clickMarkerInfoWindow=function() {
1740
1741		var marker = this;
1742
1743		var urlInfoWindow  = cmMap_rootWeb+"/cm/"+cmMap_currentWeb+"connector";
1744			urlInfoWindow += "?idContent="+marker.content.idContent;
1745			urlInfoWindow += "&alias="+marker.content.alias;
1746			urlInfoWindow += "&formatType="+cmMap_infoWindowTemplate;
1747			urlInfoWindow += "&locale="+cmMap_locale;
1748
1749		$.ajax({
1750			url: urlInfoWindow,
1751			success: function(htmlInfoWindow){
1752
1753				// Preparamos el contenido del infoWindow
1754				var contentInfoWindow = '<div class="infoWindowWrapper">';
1755					contentInfoWindow+= '	' + htmlInfoWindow;
1756					contentInfoWindow+= '	<div class="infoWindowUrl">';
1757					contentInfoWindow+= '		<a href="/'+marker.content.alias+'/'+cmMap_lang+'/'+marker.content.pathName+'" class="readMore">'+resolveMessageinGmaps('{readMore}')+'</a>';
1758					contentInfoWindow+= '	</div>';
1759					contentInfoWindow+= '</div>';
1760				
1761				var $contentInfoWindow = $(contentInfoWindow);
1762
1763				// Borramos el anterior infoWindow, creamos y abrimos
1764				if(cmMap_oldInfoWindow) {
1765					cmMap_oldInfoWindow.close();
1766				}
1767				cmMap_oldInfoWindow = new google.maps.InfoWindow();
1768				if(cmMap_maxWidthInfoWindow != 'auto') {
1769					cmMap_oldInfoWindow.setOptions({ maxWidth: cmMap_maxWidthInfoWindow });
1770				}
1771				cmMap_oldInfoWindow.setPosition(marker.center);
1772				cmMap_oldInfoWindow.setContent($contentInfoWindow.get(0));
1773				cmMap_oldInfoWindow.open(googleMapObject.cmMap);
1774
1775				// Si tenemos alguna funcion personalizada a nivel de proyecto que quiera
1776				// realizar alguna terea alternativa una vez abierto un infoWindow, la llamamos...
1777				if(typeof(cmMap_customAfterOpenInfoWindow) == 'function') {
1778					cmMap_customAfterOpenInfoWindow(googleMapObject, cmMap_oldInfoWindow, marker);
1779				}
1780
1781			}
1782		});
1783
1784	}
1785
1786    /**
1787     * Función que limpia los marcadores de la llamada json
1788     * @memberOf MapsApi
1789     */
1790	googleMapObject.cmMap_clearMarkersJSON=function() {
1791
1792		if(googleMapObject.cmMap_jsonMarkers.length != 0) {
1793			for(var i = 0; i < googleMapObject.cmMap_jsonMarkers.length; i++) {
1794				if(googleMapObject.cmMap_jsonMarkers[i]) {
1795					googleMapObject.cmMap_jsonMarkers[i].setMap(null);
1796				}
1797			}
1798			cmMap_bounds = new google.maps.LatLngBounds();
1799			googleMapObject.cmMap_jsonMarkers = new Array();
1800		}
1801
1802		if(googleMapObject.cmMap_jsonPolys.length != 0) {
1803			for(var i = 0; i < googleMapObject.cmMap_jsonPolys.length; i++) {
1804				if(googleMapObject.cmMap_jsonPolys[i]) {
1805					if(googleMapObject.cmMap_jsonPolys[i].points) {
1806						for(var j = 0; j < googleMapObject.cmMap_jsonPolys[i].points.length; j++) {
1807							googleMapObject.cmMap_jsonPolys[i].points[j].setMap(null);
1808						}
1809					} else {
1810						googleMapObject.cmMap_jsonPolys[i].setMap(null);
1811						if(googleMapObject.cmMap_jsonPolys[i].markersInRoute) {
1812							for(var j = 0; j < googleMapObject.cmMap_jsonPolys[i].markersInRoute.length; j++) {
1813								googleMapObject.cmMap_jsonPolys[i].markersInRoute[j].setMap(null);
1814							}
1815						}
1816					}
1817				}
1818			}
1819			googleMapObject.cmMap_jsonPolys = new Array();
1820		}
1821
1822	}
1823
1824    /**
1825     * @memberOf MapsApi
1826     */
1827	googleMapObject.cmMap_afterParsing = function() {
1828
1829		// Centramos en el mapa y aplicamos el zoom correspondiente
1830		googleMapObject.cmMap_setCenterAndZoom();
1831		
1832		//Se aplica el tipo de mapa correspondiente
1833		if(googleMapObject.cmMap_mapTypeId!=cmMap_mapTypeId){
1834			googleMapObject.cmMap.setMapTypeId(googleMapObject.cmMap_mapTypeId);
1835		}
1836		
1837		//solo creamos menu si no estamos en modo editable, es decir en modo usuario
1838		if(!googleMapObject.cmMap_editableMode){
1839			if(googleMapObject.cmMap_container.data('hideMenu')==undefined || !googleMapObject.cmMap_container.data('hideMenu')) {
1840				var cmMap_menuMarker = new cmMap_menu(googleMapObject.cmMap_container);
1841				cmMap_menuMarker.cmMap_createMenu();
1842			}
1843		}
1844
1845		// Si la variable cmMap_showDirections existe y vale true, mostramos el panel de direcciones
1846		if(!googleMapObject.cmMap_editableMode && typeof(cmMap_showDirectionsFromMarkers) == 'boolean' && cmMap_showDirectionsFromMarkers) {
1847			cmMap_createNewRouteFromMarkers();
1848		}
1849		
1850		//si se esta mostrando el formulario de como llegar desde el principio asignamos los eventos.
1851		if(cmMap_showForm){
1852			var _showMapFormContainer=$("div.showMapFormContainer");
1853			$("form",_showMapFormContainer).unbind("submit").submit(function(){
1854				googleMapObject.cmMap_calculateCustomRoute('markerNotInRoute',0);
1855				return false;
1856			});
1857			
1858			$("#gmSearchResetButton",_showMapFormContainer).unbind("click").click(function(){
1859				googleMapObject.cmMap_hideAddressPanel();
1860				return false;
1861			});
1862
1863			if (navigator.geolocation) {
1864				navigator.geolocation.getCurrentPosition(function(position) {
1865					// Success: buscamos desde la ubicacion actual del usuario
1866					googleMapObject.cmMap_howToArriveFromLocation(position.coords.latitude, position.coords.longitude);
1867				}, function() {
1868					// Error: no hacemos nada
1869				});
1870			}
1871		}
1872
1873		// Si tenemos una caja de busqueda asociada al mapa adjuntamos los eventos correspondientes
1874		if(cmMap_showSearchBox && !$("body").hasClass("cmMap_lightbox")){
1875			var searchFormBox = $("div.cmMap_searchBox", googleMapObject.cmMap_container);
1876
1877			if(searchFormBox.length == 0) {
1878				searchFormBox = $(' \
1879					<div class="cmMap_searchBox"> \
1880						<form class="cmMap_searchBoxForm" action=""> \
1881							<div class="input-group"> \
1882								<label for="mapApiAddress" class="sr-only">'+resolveMessageinGmaps('{directionsSearch}')+'</label> \
1883								<input name="address" id="mapApiAddress" type="text" class="form-control" placeholder="'+resolveMessageinGmaps('{directionsSearch}')+'" value=""/> \
1884								<span class="input-group-btn"> \
1885									<button type="button" class="btn btn-default btn-dir-clean hide" title="'+resolveMessageinGmaps('{directionsClean}')+'"><span class="fa fa-remove"></span><span class="sr-only">'+resolveMessageinGmaps('{directionsClean}')+'</span></button> \
1886									<button type="submit" class="btn btn-default btn-dir-search" title="'+resolveMessageinGmaps('{directionsSearch}')+'"><span class="fa fa-search"></span><span class="sr-only">'+resolveMessageinGmaps('{directionsSearch}')+'</span></button> \
1887								</span> \
1888							</div> \
1889						</form> \
1890					</div> \
1891				');
1892				googleMapObject.cmMap_container.append(searchFormBox);
1893			}
1894
1895			if(searchFormBox.length > 0) {
1896				var $formSearchBox = $("form", searchFormBox);
1897
1898				$("button.btn-dir-clean", $formSearchBox).off("click").on("click", function() {
1899						if(googleMapObject.searchBoxMarker) {
1900							googleMapObject.searchBoxMarker.setMap(null);
1901						}
1902						$(this).addClass("hide");
1903						$("input.form-control", $formSearchBox).val("").focus();
1904				});
1905
1906				$formSearchBox.off("submit").on("submit", function() {
1907
1908					var address = $("input", $(this)).val();
1909					var geocoder = new google.maps.Geocoder();
1910
1911					geocoder.geocode({'address': address}, function(results, status) {
1912						if(googleMapObject.searchBoxMarker) {
1913							googleMapObject.searchBoxMarker.setMap(null);
1914						}
1915						if (status === google.maps.GeocoderStatus.OK) {
1916							$("button.btn-dir-clean", $formSearchBox).removeClass("hide");
1917							googleMapObject.cmMap.setCenter(results[0].geometry.location);
1918							googleMapObject.searchBoxMarker = new google.maps.Marker({
1919								map: googleMapObject.cmMap,
1920								position: results[0].geometry.location
1921							});
1922							googleMapObject.cmMap.setZoom(7);
1923						} else {
1924							alert(resolveMessageinGmaps('{notFindAddress}'));
1925						}
1926					});
1927
1928					return false;
1929				});
1930
1931			}
1932		}
1933
1934	}
1935
1936
1937    /**
1938     * Función que pone una tooltip al polígono o linea
1939     * @param poly - polyType
1940     * @memberOf MapsApi
1941     */
1942	var cmMap_initPolyTooltip=function(poly){
1943
1944		google.maps.event.addListener(poly,"mousemove",function(e){
1945
1946			var _tooltipPolys = $("#tooltipPolys");
1947			if(_tooltipPolys.length == 0) {
1948				_tooltipPolys = $(' \
1949					<div id="tooltipPolys" class="tooltip top" role="tooltip"> \
1950						<div class="tooltip-arrow"></div> \
1951						<div class="tooltip-inner"></div> \
1952					</div> \
1953				');
1954				$("body").append(_tooltipPolys);
1955				$("div.tooltip-inner", _tooltipPolys).text(this.title);
1956				_tooltipPolys.css({
1957					"opacity": ".9",
1958					"position":"absolute"
1959				});
1960			}
1961
1962			// Buscamos el objeto de tipo evento, ya que el metodo del api de google maps no nos lo da
1963			var event = null;
1964			if(e && typeof(Object) == 'function' && typeof(Object.keys) == 'function') {
1965				var k = Object.keys(e);
1966				for(var i = 0; i < k.length; i++) {
1967					var p = e[k[i]];
1968					if(p && p.type && p.type == 'mousemove') {
1969						event = p;
1970					}
1971				}
1972			}
1973
1974			if(event !== null) {
1975				var pageX = event.pageX;
1976				var pageY = event.pageY;
1977				if (pageX === undefined) {
1978					pageX = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
1979					pageY = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
1980				}
1981
1982				// Modificamos la posicion de la tooltip cada vez que se mueve el raton
1983				_tooltipPolys.css({
1984					"top":(pageY - _tooltipPolys.height() - 10)+"px",
1985					"left":(pageX - (_tooltipPolys.width() / 2))+"px"
1986				});
1987			}
1988
1989		});
1990
1991		google.maps.event.addListener(poly,"mouseout",function(e){
1992			var _tooltipPolys = $("#tooltipPolys");
1993			if(_tooltipPolys.length > 0) {
1994				_tooltipPolys.remove();
1995			}
1996		});
1997
1998	}
1999
2000    /**
2001     * Función que guarda en un array los estilos del kml
2002     * @param kmlResp
2003     * @memberOf MapsApi
2004     */
2005	var cmMap_getStyleFromKml=function(kmlResp){
2006		var idStyle=kmlResp.getAttribute("id");
2007		cmMap_styleKmlArray[idStyle]=new Array();
2008		cmMap_styleKmlArray[idStyle].srcImgMarker='';
2009		cmMap_styleKmlArray[idStyle].idImgMarker='';
2010		cmMap_styleKmlArray[idStyle].idColorOverlay='';
2011		cmMap_styleKmlArray[idStyle].alphaOverlay='';
2012		cmMap_styleKmlArray[idStyle].colorOverlay='';
2013		var iconHref = '';
2014		var _href = kmlResp.getElementsByTagName("IconStyle");
2015		if(_href.length > 0) _href = _href[0].getElementsByTagName("Icon");
2016		if(_href.length > 0) _href = _href[0].getElementsByTagName("href");
2017		if(_href.length > 0) _href = _href[0].childNodes;
2018		if(_href.length > 0) iconHref = _href[0].nodeValue;
2019		if(iconHref && iconHref != ''){
2020			cmMap_styleKmlArray[idStyle].srcImgMarker = iconHref;
2021			for (idMarkerImage in cmMap_markerImages){
2022				if(cmMap_styleKmlArray[idStyle] && cmMap_styleKmlArray[idStyle].srcImgMarker && cmMap_styleKmlArray[idStyle].srcImgMarker.indexOf(cmMap_markerImages[idMarkerImage].markerIcon)>=0){
2023					cmMap_styleKmlArray[idStyle].idImgMarker=cmMap_markerImages[idMarkerImage].idImg;
2024				}
2025			}
2026			//si el marcador no corresponde a ninguno de los asignados al proyecto, le ponemos el de por defecto
2027			if(cmMap_styleKmlArray[idStyle].idImgMarker=='')cmMap_styleKmlArray[idStyle].idImgMarker=cmMap_defaultIdImgMarker;
2028		}
2029		
2030		var lineStyleColor = '';
2031		var _color = kmlResp.getElementsByTagName("LineStyle");
2032		if(_color.length > 0) _color = _color[0].getElementsByTagName("color");
2033		if(_color.length > 0) _color = _color[0].childNodes;
2034		if(_color.length > 0) lineStyleColor = _color[0].nodeValue;
2035		if(lineStyleColor && lineStyleColor != ''){
2036			cmMap_styleKmlArray[idStyle].alphaOverlay=lineStyleColor.substring(0,2);
2037			cmMap_styleKmlArray[idStyle].colorOverlay="#"+lineStyleColor.substring(2);
2038			for (colorId in cmMap_overlayColors){
2039				if(cmMap_styleKmlArray[idStyle] && cmMap_styleKmlArray[idStyle].colorOverlay && cmMap_styleKmlArray[idStyle].colorOverlay.indexOf(cmMap_overlayColors[colorId].strokeC)>=0){
2040					cmMap_styleKmlArray[idStyle].idColorOverlay=cmMap_overlayColors[colorId].idColor;
2041				}
2042			}
2043			//si el marcador no corresponde a ninguno de los asignados al proyecto, le ponemos el de por defecto
2044			if(cmMap_styleKmlArray[idStyle].idColorOverlay==''){cmMap_styleKmlArray[idStyle].idColorOverlay=cmMap_defaultIdColor;}
2045		}
2046	}
2047
2048    /**
2049     * Función que dibuja un marcador con los datos de kml
2050     * @param _point - Punto
2051     * @param {string} _overlayName - Nombre
2052     * @param {string} _overlayDescription - Descripción
2053     * @param {string} _overlayLink - Link
2054     * @param {string} _overlayStyle - Style
2055     * @memberOf MapsApi
2056     */
2057	var cmMap_drawMarkerFromKml=function(_point,_overlayName,_overlayDescription,_overlayLink,_overlayStyle){
2058		var _overlayCoords, _overlayLat, _overlayLng, _overlayLatLng = null;
2059		_overlayCoords = _point.getElementsByTagName("coordinates");
2060		if(_overlayCoords.length > 0) {
2061			_overlayCoords = _overlayCoords[0].childNodes;
2062			if(_overlayCoords.length > 0) _overlayCoords = _overlayCoords[0].nodeValue;
2063			if(_overlayCoords && _overlayCoords != '') {
2064				_overlayLng = _overlayCoords.split(',')[0];
2065				_overlayLat = _overlayCoords.split(',')[1];
2066				_overlayLatLng = new google.maps.LatLng(_overlayLat,_overlayLng);
2067				cmMap_bounds.extend(_overlayLatLng);
2068			}
2069		}
2070		// Si tenemos marcador lo creamos
2071		if(_overlayLatLng != null) {
2072			if(cmMap_styleKmlArray[_overlayStyle]){
2073				var _idImgForMarker=(cmMap_styleKmlArray[_overlayStyle].idImgMarker=='')?cmMap_defaultIdImgMarker:cmMap_styleKmlArray[_overlayStyle].idImgMarker;
2074			}else if(cmMap_markerImages[_overlayStyle]){
2075				var _idImgForMarker=(cmMap_markerImages[_overlayStyle].idImg=='')?cmMap_defaultIdImgMarker:cmMap_markerImages[_overlayStyle].idImg;
2076			}else{
2077				var _idImgForMarker=cmMap_defaultIdImgMarker;
2078			}
2079			var cmMap_markerOptionsFromKml={icon: cmMap_markerImages[_idImgForMarker].icon,shadow:googleMapObject.cmMap_defaultShadowMarker,draggable:googleMapObject.cmMap_editableMode};
2080			cmMap_createMarkerAndInfowin(cmMap_markerOptionsFromKml,_overlayLatLng,'markerNotInRoute',true,false,true,true,cmMap_getOverlayArray(_overlayName,_overlayDescription,_overlayLink,_idImgForMarker));
2081		}
2082	}
2083
2084    /**
2085     * Función que dibuja un polígono con los datos de kml
2086     * @param _polygon - Polígono
2087     * @param {string} _overlayName - Nombre
2088     * @param {string} _overlayDescription - Descripción
2089     * @param {string} _overlayLink - Link
2090     * @param {string} _overlayStyle - Style
2091     * @param _saveOverlay
2092     * @memberOf MapsApi
2093     */
2094	var cmMap_drawPolygonFromKml=function(_polygon,_overlayName,_overlayDescription,_overlayLink,_overlayStyle,_saveOverlay){
2095		var _coordinates = _polygon.getElementsByTagName("coordinates");
2096		if(_coordinates.length > 0) {
2097			var _overlayCoordsToCreate=cmMap_getCoordsFromKml(_coordinates[0],_saveOverlay);
2098			if(_overlayCoordsToCreate.length > 0) {
2099				if(cmMap_styleKmlArray[_overlayStyle]){
2100					var _idColorForOverlay=(cmMap_styleKmlArray[_overlayStyle].idColorOverlay=='')?cmMap_defaultIdColor:cmMap_styleKmlArray[_overlayStyle].idColorOverlay;
2101				}else if(cmMap_overlayColors[_overlayStyle.replace('polygon_','')]) {
2102					var _idColorForOverlay=(cmMap_overlayColors[_overlayStyle.replace('polygon_','')].idColor=='')?cmMap_defaultIdColor:cmMap_overlayColors[_overlayStyle.replace('polygon_','')].idColor;
2103				}else{
2104					var _idColorForOverlay=cmMap_defaultIdColor;
2105				}
2106				var newOverlay = new google.maps.Polygon({
2107					paths: _overlayCoordsToCreate,
2108					title: _overlayName,
2109					editable:googleMapObject.cmMap_editableMode,
2110					strokeColor: cmMap_overlayColors[_idColorForOverlay].strokeC,
2111					strokeOpacity: cmMap_overlayColors[_idColorForOverlay].strokeO,
2112					strokeWeight: cmMap_overlayColors[_idColorForOverlay].strokeW,
2113					fillColor: cmMap_overlayColors[_idColorForOverlay].fillC,
2114					fillOpacity: cmMap_overlayColors[_idColorForOverlay].fillO
2115				});
2116				cmMap_initPolyTooltip(newOverlay);
2117				newOverlay.setMap(googleMapObject.cmMap);
2118		
2119				if(_saveOverlay) {
2120					cmMap_newOverlayLatLng='';
2121					cmMap_saveOverlayAndCreateInfowin(newOverlay,'polygon',true,false,true,true,cmMap_getOverlayArray(_overlayName,_overlayDescription,_overlayLink,_idColorForOverlay));
2122				}
2123			}
2124		}
2125	}
2126
2127    /**
2128     * Función que dibuja una ruta con los datos de kml
2129     * @param {string} _overlayCoordsToCreate
2130     * @param {string} _overlayName - Nombre
2131     * @param {string} _overlayDescription - Descripción
2132     * @param {string} _overlayLink - Link
2133     * @memberOf MapsApi
2134     */
2135	var cmMap_drawRouteFromKml=function(_overlayCoordsToCreate,_overlayName,_overlayDescription,_overlayLink){
2136		//como maximo puede haber 8 waypoints, es decir 10
2137		if(_overlayCoordsToCreate.length<=10){
2138			cmMap_markersRouteLatLng=_overlayCoordsToCreate;
2139		}else{
2140			cmMap_markersRouteLatLng[0]=_overlayCoordsToCreate[0];
2141			cmMap_markersRouteLatLng[cmMap_MaxWaypoints+1]=_overlayCoordsToCreate[_overlayCoordsToCreate.length-1];
2142			var idCoordsToCreate = parseInt((_overlayCoordsToCreate.length-parseInt(_overlayCoordsToCreate.length/cmMap_MaxWaypoints))/cmMap_MaxWaypoints);
2143			for(var i=1;i<(cmMap_MaxWaypoints+1);i++){
2144				cmMap_markersRouteLatLng[i]=_overlayCoordsToCreate[parseInt(idCoordsToCreate*i)];
2145			}
2146		}
2147		cmMap_initialMarkerRoute=cmMap_createMarkerAndInfowin(cmMap_markerOptionsInRoute,cmMap_markersRouteLatLng[0],'markerInRoute',cmMap_createInfowinMarkerRoute,false,true,false,{});
2148		cmMap_generateRoute(false,true,false,true,cmMap_getOverlayArray(_overlayName,_overlayDescription,_overlayLink,null),0);
2149	}
2150
2151    /**
2152     * Función que dibuja una linea con los datos de kml
2153     * @param _overlayCoordsToCreate
2154     * @param {string} _overlayName - Nombre
2155     * @param {string} _overlayDescription - Descripción
2156     * @param {string} _overlayLink - Link
2157     * @param {string} _overlayStyle - Style
2158     * @memberOf MapsApi
2159     */
2160	var cmMap_drawLineFromKml=function(_overlayCoordsToCreate,_overlayName,_overlayDescription,_overlayLink,_overlayStyle){
2161		if(cmMap_styleKmlArray[_overlayStyle]){
2162			var _idColorForOverlay=(cmMap_styleKmlArray[_overlayStyle].idColorOverlay=='')?cmMap_defaultIdColor:cmMap_styleKmlArray[_overlayStyle].idColorOverlay;
2163		}else if(cmMap_overlayColors[_overlayStyle.replace('polyline_','')]) {
2164			var _idColorForOverlay=(cmMap_overlayColors[_overlayStyle.replace('polyline_','')].idColor=='')?cmMap_defaultIdColor:cmMap_overlayColors[_overlayStyle.replace('polyline_','')].idColor;
2165		}else{
2166			var _idColorForOverlay=cmMap_defaultIdColor;
2167		}
2168		var newOverlay = new google.maps.Polyline({
2169			path: _overlayCoordsToCreate,
2170			title: _overlayName,
2171			editable:googleMapObject.cmMap_editableMode,
2172			strokeColor: cmMap_overlayColors[_idColorForOverlay].strokeC,
2173			strokeOpacity: cmMap_overlayColors[_idColorForOverlay].strokeO,
2174			strokeWeight: cmMap_overlayColors[_idColorForOverlay].strokeW
2175		});
2176		cmMap_initPolyTooltip(newOverlay);
2177		newOverlay.setMap(googleMapObject.cmMap);
2178	
2179		cmMap_newOverlayLatLng='';
2180		cmMap_saveOverlayAndCreateInfowin(newOverlay,'polyline',true,false,true,true,cmMap_getOverlayArray(_overlayName,_overlayDescription,_overlayLink,_idColorForOverlay));
2181	}
2182
2183    /**
2184     * Función que obtiene coordenadas de un elemeto desde el kml y lo devuelve como un array
2185     * @param _overlayCoords - Coordenadas
2186     * @param _saveOverlay
2187     * @returns {Array} Array de coordenadas
2188     * @memberOf MapsApi
2189     */
2190	var cmMap_getCoordsFromKml=function(_overlayCoords,_saveOverlay){
2191		var _overlayCoordsToCreate=new Array();
2192		_overlayCoords = _overlayCoords.textContent || _overlayCoords.text;
2193		if(_overlayCoords && _overlayCoords != '') {
2194			var _overlayLat, _overlayLng, _overlayLatLng = null;
2195			var _overlayCoordsArray = _overlayCoords.split('\n');
2196			for (var i = 0; i < _overlayCoordsArray.length; i++){
2197				_overlayCoordsArray[i] = $.trim(cmMap_removeSpaces(_overlayCoordsArray[i]));
2198				if(_overlayCoordsArray[i] != ''){
2199					_overlayLng = _overlayCoordsArray[i].split(',')[0];
2200					_overlayLat = _overlayCoordsArray[i].split(',')[1];
2201					_overlayLatLng = new google.maps.LatLng(_overlayLat,_overlayLng);
2202					_overlayCoordsToCreate.push(_overlayLatLng);
2203					if(_saveOverlay) cmMap_bounds.extend(_overlayLatLng);
2204				}
2205			}
2206		}
2207		return _overlayCoordsToCreate;
2208	}
2209
2210    /**
2211     * Función que devuelve el array de opciones de cada marcador
2212     * @param {string} _overlayName - Nombre
2213     * @param {string} _overlayDescription - Descripción
2214     * @param {string} _overlayLink - Link
2215     * @param {string} _styleId - Id
2216     * @returns {Array} Array de opciones
2217     * @memberOf MapsApi
2218     */
2219	var cmMap_getOverlayArray=function(_overlayName, _overlayDescription, _overlayLink, _styleId) {
2220		var arrayOverlay = new Array();
2221		arrayOverlay['name'] = _overlayName;
2222		arrayOverlay['description'] = _overlayDescription;
2223		if(_styleId) arrayOverlay['styleId'] = _styleId;
2224		arrayOverlay['url'] = '';
2225		arrayOverlay['idContent'] = '';
2226		arrayOverlay['alias'] = '';
2227		arrayOverlay['content'] = '';
2228		// Si encontramos la cadena INTERNAL_URL en el enlace, se trata de un enlace a contenido
2229		if(_overlayLink && _overlayLink.indexOf('INTERNAL_URL') != -1) {
2230			var regex = new RegExp('\\[INTERNAL_URL idContent=\"([0-9]+)\" alias=\"([^\"\\s]+)+\" name=\"([^\"]+)+\"\\]');
2231			var results = regex.exec(_overlayLink);
2232			if(results != null) {
2233				arrayOverlay['idContent'] = results[1];
2234				arrayOverlay['alias'] = results[2];
2235				arrayOverlay['content'] = results[3];
2236			}
2237		}
2238		else {
2239			arrayOverlay['url'] = (_overlayLink)?_overlayLink:'';
2240		}
2241		return arrayOverlay;
2242	}
2243
2244    /**
2245     * Función que muestra el botón de marcadores deshabilitado
2246     * @param controlDiv - Div
2247     * @memberOf MapsApi
2248     */
2249	var cmMap_markerDisControl=function(controlDiv) {
2250		if($.browser.msie && $.browser.version == 8) {
2251			controlDiv.style.padding = '3px 5px 5px 0';
2252		}else{
2253			controlDiv.style.padding = '5px 5px 5px 0';
2254		}
2255	
2256		markerDisabledControl = document.createElement('DIV');
2257		markerDisabledControl.className='markerDisButton';
2258		markerDisabledControl.style.backgroundColor = 'white';
2259		markerDisabledControl.style.borderStyle = 'solid';
2260		markerDisabledControl.style.borderWidth = '0';
2261		markerDisabledControl.style.cursor = 'pointer';
2262		markerDisabledControl.style.textAlign = 'center';
2263		markerDisabledControl.style.height = '26px';
2264		markerDisabledControl.style.width = '25px';
2265		markerDisabledControl.style.display='none';
2266		markerDisabledControl.title = resolveMessageinGmaps('{insertMarker}');
2267		markerDisabledControl.innerHTML = '<img src="'+cmMap_rootWeb+'/edit/wizard/images/gmaps/markerDisabled.png"/>';
2268		controlDiv.appendChild(markerDisabledControl);
2269	}
2270
2271    /**
2272     * Función que crea un nuevo panel de control con funcionalidades como "dibujar linea por carreteras"...
2273     * @param controlDiv - Div
2274     * @memberOf MapsApi
2275     */
2276	var cmMap_ownDrawingPanelControl=function(controlDiv) {
2277		if($.browser.msie && $.browser.version == 8) {
2278			controlDiv.style.padding = '3px 5px 5px 0';
2279		}else{
2280			controlDiv.style.padding = '5px 5px 5px 0';
2281		}
2282		
2283		if(googleMapObject.cmMap_createRoutesMode){
2284			var createRouteButton = document.createElement('DIV');
2285			createRouteButton.className='newButton createRouteButton';
2286			createRouteButton.style.backgroundColor = 'white';
2287			createRouteButton.style.borderStyle = 'solid';
2288			createRouteButton.style.borderWidth = '0';
2289			createRouteButton.style.cursor = 'pointer';
2290			createRouteButton.style.textAlign = 'center';
2291			createRouteButton.style.height = '26px';
2292			createRouteButton.style.width = '25px';
2293			createRouteButton.title = resolveMessageinGmaps('{insertRoute}');
2294			createRouteButton.innerHTML = '<img src="'+cmMap_rootWeb+'/edit/wizard/images/gmaps/createRoute.png"/>';
2295			controlDiv.appendChild(createRouteButton);
2296			cmMap_ownDrawingButtons['createRoute']=new Array();
2297			cmMap_ownDrawingButtons['createRoute'].boton=createRouteButton;
2298			
2299			
2300			// crea el event listeners al botón de crear ruta
2301			google.maps.event.addDomListener(cmMap_ownDrawingButtons['createRoute'].boton, 'click', function() {
2302				if(cmMap_drawingMode!='createRoute' && cmMap_markersRouteLatLng.length!=(cmMap_MaxWaypoints+2)){
2303					cmMap_buttonOff('clear');
2304					cmMap_drawingMode='createRoute';
2305					$("img",createRouteButton).attr('src',''+cmMap_rootWeb+'/edit/wizard/images/gmaps/createRouteSel.png');
2306					cmMap_clickNullButton=false;
2307					cmMap_drawingManager.setDrawingMode(null);
2308				}
2309			});
2310		}
2311		
2312		cmMap_clearButton = document.createElement('DIV');
2313		cmMap_clearButton.className='newButton clearButton';
2314		cmMap_clearButton.style.backgroundColor = 'white';
2315		cmMap_clearButton.style.borderStyle = 'solid';
2316		cmMap_clearButton.style.borderWidth = '0';
2317		cmMap_clearButton.style.cursor = 'pointer';
2318		cmMap_clearButton.style.textAlign = 'center';
2319		cmMap_clearButton.style.height = '26px';
2320		cmMap_clearButton.style.width = '26px';
2321		cmMap_clearButton.title = resolveMessageinGmaps('{cleanMap}');
2322		cmMap_clearButton.innerHTML = '<img src="'+cmMap_rootWeb+'/edit/wizard/images/gmaps/clear.png"/>';
2323		controlDiv.appendChild(cmMap_clearButton);
2324		cmMap_ownDrawingButtons['clear']=new Array();
2325		cmMap_ownDrawingButtons['clear'].boton=cmMap_clearButton;
2326		
2327		google.maps.event.addDomListener(cmMap_ownDrawingButtons['clear'].boton, 'click', function() {
2328			cmMap_ClearAll();
2329		});
2330	
2331	}
2332
2333    /**
2334     * Función para limpiar todos los elementos del mapa
2335     * @memberOf MapsApi
2336     */
2337	var cmMap_ClearAll=function(){
2338		if(googleMapObject.cmMap_createRoutesMode) cmMap_buttonOff('createRoute');
2339		cmMap_drawingMode='clear';
2340		$("img",cmMap_clearButton).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/clearSel.png');
2341		cmMap_clickNullButton=false;
2342		cmMap_drawingManager.setDrawingMode(null);
2343		
2344		cmMap_closeOldWindow();
2345		//eliminas marcadores, poligonos, lineas
2346		for (idTypeOfOverlay in cmMap_overlaysInMap){
2347			cmMap_deleteOverlaysInMap(idTypeOfOverlay);
2348			cmMap_infoWindowInMap[idTypeOfOverlay]=[];
2349		}
2350		
2351		if(googleMapObject.cmMap_createRoutesMode){
2352			cmMap_changeRouteByDrag=false;
2353			if(cmMap_markersRouteLatLng.length==(cmMap_MaxWaypoints+2)){
2354				//lanzamos evento de que el maximo punto de la ruta, ya no ha sido alcanzado
2355				googleMapObject.cmMap_container.trigger('maxWaypointNotReach');
2356			}
2357			if(cmMap_markersRouteLatLng.length>1){
2358				//eliminamos la ruta
2359				cmMap_directionsDisplay.setMap(null);
2360			}
2361			cmMap_markersRouteLatLng=[];
2362			if(cmMap_initialMarkerRoute){
2363				cmMap_initialMarkerRoute.setMap(null);
2364				cmMap_initialMarkerRoute='';
2365			}
2366		}
2367		
2368		//si estamos en modo edicion tipo localizacion, lanzamos el  evento de que se puede poner un marcador en el mapa
2369		if(googleMapObject.cmMap_editableMode && googleMapObject.cmMap_typeParam=='location'){
2370			googleMapObject.cmMap_container.trigger('maxPointNoReach');
2371		}
2372	}
2373
2374    /**
2375     * Función que inicializa diferentes eventos
2376     * @memberOf MapsApi
2377     */
2378	var cmMap_initializeEvents=function(){
2379		//SI ESTAMOS EN MODO EDICION
2380		if(googleMapObject.cmMap_editableMode){
2381			
2382			//efecto visual al pasar por los botones
2383			for (idButton in cmMap_ownDrawingButtons){
2384				cmMap_buttonHover(idButton);
2385			}
2386			
2387			google.maps.event.addDomListener(cmMap_drawingManager, 'drawingmode_changed', function(event) {
2388				if(cmMap_drawingManager.getDrawingMode()!=null){
2389					for (idButton in cmMap_ownDrawingButtons){
2390						cmMap_buttonOff(idButton);
2391					}
2392					cmMap_drawingMode='';
2393				}
2394				//si cambia al modo null, detectamos si lo hemos puesto nosotros para iniciar funcionalidades de nuestros eventos o por hacer click en el botón
2395				if(cmMap_drawingManager.getDrawingMode()==null){
2396					if(cmMap_clickNullButton){
2397						//hemos hecho click en el botón de la mano
2398						for (idButton in cmMap_ownDrawingButtons){
2399							cmMap_buttonOff(idButton);
2400						}
2401						cmMap_drawingMode='';
2402					}else{
2403						//viene de que hemos activado nuestras funcionalidades,pero la proxima vez que entre es porque le hemos dado click nosotros
2404						cmMap_clickNullButton=true;
2405					}
2406					//si estamos en modo edicion tipo localizacion y hay ningun marcador, insertamos la imagen de deshabilitado
2407					if(googleMapObject.cmMap_editableMode && googleMapObject.cmMap_typeParam=='location' && cmMap_contMarkerInMap>0){
2408						cmMap_drawingManager.setOptions({drawingControlOptions: {drawingModes: []}});
2409						markerDisabledControl.style.display='block';
2410					}
2411				}
2412			});
2413
2414            /**
2415			 * Evento al terminar de poner una forma en el mapa
2416			 * @memberOf MapsApi
2417             */
2418			google.maps.event.addListener(cmMap_drawingManager, 'overlaycomplete', function(event) {
2419				if(event.type == google.maps.drawing.OverlayType.MARKER) {
2420					//si estamos en modo edicion tipo localizacion y no hay ningun marcador, se puede insertar, si no le borramos y lo indicamos
2421					if(!(googleMapObject.cmMap_editableMode && googleMapObject.cmMap_typeParam=='location' && cmMap_contMarkerInMap>0)){
2422						cmMap_saveOverlayAndCreateInfowin(event.overlay,'markerNotInRoute',true,true,true,false,{});
2423						//indicamos si estamos en modo edicion tipo localizacion que se ha alcanzado el maximo de marcadores (1)
2424						if(googleMapObject.cmMap_editableMode && googleMapObject.cmMap_typeParam=='location'){googleMapObject.cmMap_container.trigger('maxPointReach');}
2425					}else{
2426						event.overlay.setMap(null);
2427						messageBox(true,resolveMessageinGmaps('{notInsertMarker}'));
2428					}
2429				}else{
2430					var newOverlay=event.overlay;
2431					var evenType='';
2432					if(event.type == google.maps.drawing.OverlayType.RECTANGLE) {
2433						evenType='rectangule';
2434						cmMap_newOverlayLatLng=newOverlay.getBounds().getCenter();
2435					}
2436					if(event.type == google.maps.drawing.OverlayType.POLYGON) {
2437						evenType='polygon';
2438						var path = newOverlay.getPath();
2439						//obtenemos la ultima
2440						//cmMap_newOverlayLatLng=path.getAt(path.length-1);
2441						cmMap_newOverlayLatLng=path.getAt(parseInt(path.length/2));
2442					}
2443					if( event.type == google.maps.drawing.OverlayType.POLYLINE) {
2444						evenType='polyline';
2445						var path = newOverlay.getPath();
2446						//obtenemos la ultima
2447						cmMap_newOverlayLatLng=path.getAt(parseInt(path.length/2));
2448					}
2449					if(event.type == google.maps.drawing.OverlayType.CIRCLE) {
2450						evenType='circle';
2451						cmMap_newOverlayLatLng=newOverlay.getCenter();
2452					}
2453					cmMap_saveOverlayAndCreateInfowin(newOverlay,evenType,true,true,true,false,{});
2454				}
2455			});
2456
2457			// anadimos las coordenadas de centrado al formulario de edicion de parametros kml
2458			if(googleMapObject.cmMap_typeParam!='location'){
2459				google.maps.event.addListener(googleMapObject.cmMap, 'center_changed', function(event) {
2460					var _coords = googleMapObject.cmMap.getCenter();
2461					var _lat = parseFloat(_coords.lat()).toFixed(6);
2462					var _lng = parseFloat(_coords.lng()).toFixed(6);
2463					$("#cmMap_zoomCenter").text(_lat.toString() + ',' + _lng.toString());
2464				});
2465			}
2466			
2467			//si el tipo de parametro es localizacion
2468			if(googleMapObject.cmMap_typeParam=='location'){
2469				googleMapObject.cmMap_container.bind('maxPointReach',function(){
2470					cmMap_contMarkerInMap++;
2471					//$("button.cmMap_insertMarker").attr('disabled','disabled').addClass("disabledButton");
2472					//agregamos la imagen de deshabilitado cuando no estamos creando los marcadores desde el botón, porque es confuso
2473					if($("button.cmMap_deleteMarkerButton").length > 0) $("button.cmMap_deleteMarkerButton").show();
2474					if(cmMap_drawingManager.getDrawingMode()!='marker'){
2475						cmMap_drawingManager.setOptions({drawingControlOptions: {drawingModes: []}});
2476						markerDisabledControl.style.display='block';
2477					}
2478				});
2479				
2480				googleMapObject.cmMap_container.bind('maxPointNoReach',function(){
2481					cmMap_contMarkerInMap=0;
2482					if($("button.cmMap_deleteMarkerButton").length > 0) $("button.cmMap_deleteMarkerButton").hide();
2483					//$("button.cmMap_insertMarker").removeAttr('disabled').removeClass("disabledButton");
2484					cmMap_drawingManager.setOptions({drawingControlOptions: {drawingModes: [google.maps.drawing.OverlayType.MARKER]}});
2485					markerDisabledControl.style.display='none';
2486				});
2487			}
2488			
2489			//al cambiar el zoom en modo de edicion actualizamos el select
2490			google.maps.event.addListener(googleMapObject.cmMap, 'zoom_changed', function(event) {
2491				var zoomLevel = googleMapObject.cmMap.getZoom();
2492				if($("#cmMap_zoomLevelSelect").length > 0) {
2493					$("#cmMap_zoomLevelSelect").val(zoomLevel);
2494				}
2495			});
2496		
2497			var addressInsertInput=$("input.cmMap_addressInsertInput",cmMap_controls);
2498
2499			//formulario de coordendas
2500			var coordXInsertInput=$("input.cmMap_coordLatInsertInput",cmMap_controls);
2501			var coordYInsertInput=$("input.cmMap_coordLngInsertInput",cmMap_controls);
2502			
2503			//formulario de busqueda de un marcador
2504			$("button.cmMap_insertMarker",cmMap_controls).click(function(){
2505				if($("#cmMap_markerInsertType_0").is(":checked")) {
2506					if(addressInsertInput.val().trim()=='') {
2507						messageBoxWithAction(true,resolveMessageinGmaps('{insertAddress}'), function() {
2508							addressInsertInput.focus();
2509							window.top.hideLoadingLayer(document);
2510						});
2511					}
2512					else {
2513						cmMap_placeMarkerFromAddress(addressInsertInput.val());
2514						addressInsertInput.blur();
2515					}
2516				}
2517				if($("#cmMap_markerInsertType_1").is(":checked")){
2518					if(coordXInsertInput.val().trim()=='' || coordYInsertInput.val().trim()=='') {
2519						messageBoxWithAction(true,resolveMessageinGmaps('{insertLatLng}'), function() {
2520							if(coordXInsertInput.val().trim()=='') coordXInsertInput.focus();
2521							else if(coordYInsertInput.val().trim()=='') coordYInsertInput.focus();
2522							window.top.hideLoadingLayer(document);
2523						});
2524					}
2525					else {
2526						if(googleMapObject.cmMap_typeParam=='location' && cmMap_contMarkerInMap > 0){
2527							var myMessageBox = new window.top.MessageBox(300,130);
2528							myMessageBox.setMessage(resolveMessageinGmaps('{updateMarker}'));
2529							myMessageBox.addButton(window.top.resolveMessage('{lang_accept}'),function() {
2530								cmMap_ClearAll();
2531								var latlngToInsert = new google.maps.LatLng(coordXInsertInput.val().replace(',','.'),coordYInsertInput.val().replace(',','.'));
2532								cmMap_createMarkerAndInfowin(cmMap_markerOptions,latlngToInsert,'markerNotInRoute',true,true,true,false,{});
2533								coordXInsertInput.blur();
2534								coordYInsertInput.blur();
2535								window.top.hideLoadingLayer(document);
2536							});
2537							myMessageBox.addButton(window.top.resolveMessage('{lang_cancel}'));
2538							myMessageBox.showWindow(document);
2539						}
2540						else {
2541							if(googleMapObject.cmMap_typeParam=='location' && cmMap_contMarkerInMap > 0){
2542								cmMap_ClearAll();
2543							}
2544							var latlngToInsert = new google.maps.LatLng(coordXInsertInput.val().replace(',','.'),coordYInsertInput.val().replace(',','.'));
2545							cmMap_createMarkerAndInfowin(cmMap_markerOptions,latlngToInsert,'markerNotInRoute',true,true,true,false,{});
2546							coordXInsertInput.blur();
2547							coordYInsertInput.blur();
2548						}
2549					}
2550				}
2551				return false;
2552			});
2553			
2554			$("button.cmMap_addressInsertRouteFromHere",cmMap_controls).click(function(){
2555				if(addressInsertInput.val()!=''){
2556					cmMap_placeInitialMarkerRouteFromAddress(addressInsertInput.val());
2557					addressInsertInput.blur();
2558				}
2559				return false;
2560			});
2561			
2562			$("button.cmMap_addressInsertRouteToHere",cmMap_controls).click(function(){
2563				if(addressInsertInput.val()!=''){
2564					cmMap_placeFinalMarkerRouteFromAddress(addressInsertInput.val());
2565					addressInsertInput.blur();
2566				}
2567				return false;
2568			});
2569			
2570			$("button.cmMap_centerMap",cmMap_controls).click(function(){
2571				if($("#cmMap_markerInsertType_0").is(":checked")) {
2572					if(addressInsertInput.val().trim()=='') {
2573						messageBoxWithAction(true,resolveMessageinGmaps('{insertAddress}'), function() {
2574							addressInsertInput.focus();
2575							window.top.hideLoadingLayer(document);
2576						});
2577					}
2578					else {
2579						cmMap_centerMapFromAddress(addressInsertInput.val());
2580						addressInsertInput.blur();
2581					}
2582				}
2583				if($("#cmMap_markerInsertType_1").is(":checked")){
2584					if(coordXInsertInput.val().trim()=='' || coordYInsertInput.val().trim()=='') {
2585						messageBoxWithAction(true,resolveMessageinGmaps('{insertLatLng}'), function() {
2586							if(coordXInsertInput.val().trim()=='') coordXInsertInput.focus();
2587							else if(coordYInsertInput.val().trim()=='') coordYInsertInput.focus();
2588							window.top.hideLoadingLayer(document);
2589						});
2590					}
2591					else {
2592						if(googleMapObject.cmMap_typeParam=='location' && cmMap_contMarkerInMap > 0){
2593							cmMap_ClearAll();
2594						}
2595						var latlngToInsert = new google.maps.LatLng(coordXInsertInput.val(),coordYInsertInput.val());
2596						googleMapObject.cmMap.setCenter(latlngToInsert);
2597						coordXInsertInput.blur();
2598						coordYInsertInput.blur();
2599					}
2600				}
2601				return false;
2602			});
2603		
2604			$("button.cmMap_coordInsertRouteFromHere",cmMap_controls).click(function(){
2605				if(coordXInsertInput.val()!='' && coordYInsertInput.val()!=''){
2606					var latlngToInsert = new google.maps.LatLng(coordXInsertInput.val(),coordYInsertInput.val());
2607					googleMapObject.cmMap.setCenter(latlngToInsert);
2608					cmMap_createRouteFromHere('','',latlngToInsert,false);
2609					coordXInsertInput.blur();
2610					coordYInsertInput.blur();
2611				}
2612				return false;
2613			});
2614		
2615			$("button.cmMap_coordInsertRouteToHere",cmMap_controls).click(function(){
2616				if(coordXInsertInput.val()!='' && coordYInsertInput.val()!=''){
2617					var latlngToInsert = new google.maps.LatLng(coordXInsertInput.val(),coordYInsertInput.val());
2618					googleMapObject.cmMap.setCenter(latlngToInsert);
2619					cmMap_createRouteToHere('','',latlngToInsert,false);
2620					coordXInsertInput.blur();
2621					coordYInsertInput.blur();
2622				}
2623				return false;
2624			});
2625
2626			if($("#cmMap_customZoomLevel").length > 0){
2627				$("#cmMap_customZoomLevel").bind("click", function(){
2628					$("#cmMap_zoomLevelSelect,div.cmMap_formFieldCenter").css("visibility",($(this).is(":checked"))?"visible":"hidden");
2629				});
2630			}
2631
2632			if($("#cmMap_zoomLevelSelect").length > 0){
2633				$("#cmMap_zoomLevelSelect").bind("change", function(){
2634					googleMapObject.cmMap.setZoom(parseInt($(this).val(),10));
2635				});
2636			}
2637			
2638			$("form.cmMap_markerInsertForm",cmMap_controls).submit(function(){
2639				return false;
2640			});
2641			
2642			//formulario de guardar los cambios
2643			$("form.cmMap_saveForm").submit(function(){
2644				cmMap_closeOldWindow();
2645				if(googleMapObject.cmMap_typeParam=='location'){
2646					var finalLat = '', finalLng = '', finalMarkerId = '', finalZoomLevel = '', finalMapTypeId = '';
2647					for(var i=0;i<cmMap_overlaysInMap['markerNotInRoute'].length;i++){
2648						if(cmMap_overlaysInMap['markerNotInRoute'][i].visible){
2649
2650							// Recogemos y tratamos la latitud y longitud del marcador, formateamos los valores
2651							// a 6 decimales, lo convertimos a cadena y lo guardamos con comas
2652							finalLat = cmMap_overlaysInMap['markerNotInRoute'][i].overlay.getPosition().lat();
2653							finalLng = cmMap_overlaysInMap['markerNotInRoute'][i].overlay.getPosition().lng();
2654							if(finalLat != '') {
2655								finalLat = parseFloat(finalLat).toFixed(6);
2656								finalLat = finalLat.toString();
2657								finalLat = finalLat.replace('.',',');
2658							}
2659							if(finalLng != '') {
2660								finalLng = parseFloat(finalLng).toFixed(6);
2661								finalLng = finalLng.toString();
2662								finalLng = finalLng.replace('.',',');
2663							}
2664
2665							// Recogemos y tratamos el id de la imagen del marcador
2666							finalMarkerId = cmMap_overlaysInMap['markerNotInRoute'][i].styleId;
2667							if(finalMarkerId == '') finalMarkerId = cmMap_defaultIdImgMarker;
2668
2669							// Recogemos el nivel de zoom, si coincide con el de por defecto o no esta checkeado, lo dejamos vacio
2670							finalZoomLevel = parseInt($("#cmMap_zoomLevelSelect").val(),10);
2671							if(finalZoomLevel == cmMap_zoom || !$("#cmMap_customZoomLevel").is(":checked")) finalZoomLevel = '';
2672							
2673							finalMapTypeId = googleMapObject.cmMap.getMapTypeId();
2674							if(finalMapTypeId == cmMap_mapTypeId) finalMapTypeId = '';
2675
2676							// Eliminamos 'img_' del marcador, solo nos interesa el id
2677							if(finalMarkerId != '') finalMarkerId = finalMarkerId.replace('img_','');
2678
2679							break;
2680						}
2681					}
2682					window.top.updateGMapsLocation(parameter,parameterInstance,finalLat,finalLng,finalMarkerId,finalZoomLevel,finalMapTypeId);
2683					window.top.closeProxiaDialog(window);
2684				}else{
2685					window.top.updateGMapsKml(parameter,parameterInstance,cmMap_kmlGeneratorType());
2686					window.top.closeProxiaDialog(window);
2687				}
2688				return false;
2689			});
2690
2691			//si estamos en modo edicion tipo localizacion y hay algun marcador, mostramos el botón que elimina el punto
2692			if($("button.cmMap_deleteMarkerButton").length > 0){
2693				$("button.cmMap_deleteMarkerButton").bind("click", function(){
2694					window.top.updateGMapsLocation(parameter,parameterInstance,'','','','');
2695					window.top.closeProxiaDialog(window);
2696					return false;
2697				});
2698			}
2699
2700			//si estamos en modo edicion tipo kml y hay algun elemento en el mapa, mostramos el botón que elimina todo
2701			if($("button.cmMap_deleteItemsButton").length > 0){
2702				$("button.cmMap_deleteItemsButton").bind("click", function(){
2703					cmMap_ClearAll();
2704					window.top.updateGMapsKml(parameter,parameterInstance,'');
2705					window.top.closeProxiaDialog(window);
2706					return false;
2707				});
2708			}
2709			
2710			
2711			
2712			//si se pueden crear rutas
2713			if(googleMapObject.cmMap_createRoutesMode){
2714				//evento al hacer click en el mapa
2715				google.maps.event.addListener(googleMapObject.cmMap, 'click', function(event) {
2716					//modo crear ruta
2717					if(cmMap_drawingMode=='createRoute') {
2718						if(cmMap_markersRouteLatLng.length==(cmMap_MaxWaypoints+2)){
2719							messageBox(true,resolveMessageinGmaps('{maxPointsReach}',[cmMap_MaxWaypoints+2]));
2720						}else{
2721							cmMap_markersRouteLatLng.push( event.latLng);
2722							if(cmMap_markersRouteLatLng.length==1){
2723								cmMap_closeOldWindow();
2724								cmMap_initialMarkerRoute=cmMap_createMarkerAndInfowin(cmMap_markerOptionsInRoute,event.latLng,'markerInRoute',cmMap_createInfowinMarkerRoute,false,true,false,{});
2725							}else{
2726								cmMap_generateRoute(false,true,true,true,{},cmMap_overlaysInMap['markerInRoute'].length-1);
2727							}
2728						}
2729					}
2730				});
2731				
2732				//evento que se lanza cuando no se puede introducir mas puntos en la ruta porque se ha alcanzado el maximo permitido
2733				googleMapObject.cmMap_container.bind('maxWaypointReach',function(){
2734					//agregamos la imagen de deshabilitado cuando no estamos creando la ruta desde el botón, porque es confuso
2735					if(cmMap_drawingMode!='createRoute') {
2736						$("img",cmMap_ownDrawingButtons['createRoute'].boton).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/createRouteDisabled.png');
2737					}
2738					$("button.insertRoute").attr('disabled','disabled').addClass("disabledButton");
2739				});
2740				
2741				//evento que se lanza cuando se eliminan puntos de la ruta, todos o uno
2742				googleMapObject.cmMap_container.bind('maxWaypointNotReach',function(){
2743					if(cmMap_drawingMode=='createRoute'){
2744						$("img",cmMap_ownDrawingButtons['createRoute'].boton).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/createRouteSel.png');
2745					}else{
2746						$("img",cmMap_ownDrawingButtons['createRoute'].boton).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/createRoute.png');
2747					}
2748					$("button.insertRoute").removeAttr('disabled').removeClass("disabledButton");
2749				});
2750			}
2751			
2752			
2753			google.maps.event.addListener(googleMapObject.cmMap, 'maptypeid_changed', function(event) {
2754				googleMapObject.cmMap_mapTypeId=googleMapObject.cmMap.getMapTypeId();
2755			});
2756		}
2757		//FIN DE SI ESTAMOS EN MODO EDICION
2758		
2759		//SI NO ESTAMOS EN MODO EDICION
2760		// Si tenemos formulario repetimos la llamada json al cambiar de zoom y al arrastrar el mapa
2761		if(!googleMapObject.cmMap_editableMode && googleMapObject.cmMap_searchForm != null){
2762
2763			//al cambiar el zoom en modo de edicion actualizamos el select
2764			google.maps.event.addListener(googleMapObject.cmMap, 'zoom_changed', function(event) {
2765				if (googleMapObject.cmMap.getZoom() < cmMap_minZoomLevel) {
2766					googleMapObject.cmMap.setZoom(cmMap_minZoomLevel);
2767					return;
2768				}
2769				this.zoomChanged = true;
2770			});
2771
2772			google.maps.event.addListener(googleMapObject.cmMap, 'bounds_changed', function(event) {
2773				if(this.zoomChanged) {
2774					this.zoomChanged = false;
2775  					// Si tenemos un buscador asociado al mapa realizamos la busqueda cada vez que cambia el zoom
2776					googleMapObject.cmMap_doSearch(googleMapObject.cmMap_searchForm,false);
2777				}
2778			});
2779			
2780			google.maps.event.addListener(googleMapObject.cmMap, 'dragend', function(event) {
2781				// Si tenemos un buscador asociado al mapa realizamos la busqueda cada vez que cambia el zoom
2782				googleMapObject.cmMap_doSearch(googleMapObject.cmMap_searchForm,false);
2783			});
2784
2785		}
2786		//FIN DE SI NO ESTAMOS EN MODO EDICION
2787
2788		google.maps.event.addListener(cmMap_directionsDisplay, 'directions_changed', function(event) {
2789			//indica que se ha activado este evento porque le hemos dado a generar ruta
2790			if(!cmMap_changeRouteByDrag){
2791				cmMap_changeRouteByDrag=true;
2792			}else{
2793			//indica que se ha activado este evento porque hemos modificado la ruta, pero no le ha sido a traves del botón, sino por mover puntos existentes de la ruta (drag)
2794				cmMap_fireActionWhenRouteDrag();
2795			}
2796		});
2797
2798		//si estamos en el prettyphoto y pasamos a modo street view, ocultamos el icono de cerrar el prettyphoto
2799		var cmMap_streetView = googleMapObject.cmMap.getStreetView();
2800		google.maps.event.addListener(cmMap_streetView, 'visible_changed', function() {
2801		if(window.top){
2802				var cmMap_closeModalLink = $("div.proxiaIframe .pp_close",window.top.document);
2803				if(cmMap_closeModalLink.length > 0){
2804					if(cmMap_streetView.getVisible()){
2805						cmMap_closeModalLink.css('display','none');
2806					}else{
2807						cmMap_closeModalLink.fadeIn(1000);
2808					}
2809				}
2810			}
2811		});
2812	}
2813
2814    /**
2815     * Función que se lanza cuando se mueve una ruta con el ratón
2816     * @memberOf MapsApi
2817     */
2818	var cmMap_fireActionWhenRouteDrag=function(){
2819		if(cmMap_markersRouteLatLng.length==(cmMap_MaxWaypoints+2)){
2820			messageBox(true,resolveMessageinGmaps('{maxPointsReach}', [cmMap_MaxWaypoints+2]));
2821		}else{
2822			cmMap_getMarkerInRouteLatLng();
2823		}	
2824		//volvemos a generar la ruta, para que los marcadores se guarden correctamente. (necesario en caso de guardarlos)
2825		//se hace aunque no se hayan cambiado los marcadores, porque ya no puede haber mas, ya que al arrastrar a veces no vuelve a su sitio
2826		cmMap_generateRoute(false, true,false,true,{},0);
2827	}
2828
2829    /**
2830     * Función que obtiene las coordenadas de los marcadores de una ruta y las guarda en el array: cmMap_markersRouteLatLng
2831     * @memberOf MapsApi
2832     */
2833	var cmMap_getMarkerInRouteLatLng=function(){
2834		cmMap_markersRouteLatLng=[];
2835		var wp;
2836		directionResult=cmMap_directionsDisplay.getDirections();
2837		for(var j=0;j<directionResult.routes[0].legs.length;j++){
2838			var myRoute = directionResult.routes[0].legs[j];
2839			if(j==0)cmMap_markersRouteLatLng.push(myRoute.start_location);
2840			var wp = myRoute.via_waypoints 
2841			for(var i=0;i<wp.length;i++){
2842				cmMap_markersRouteLatLng.push(wp[i]);
2843			}
2844			cmMap_markersRouteLatLng.push(myRoute.end_location)
2845		}
2846	}
2847
2848    /**
2849     * Función que pone el botón como no seleccionado
2850     * @param {string} functionallity
2851     * @memberOf MapsApi
2852     */
2853	var cmMap_buttonOff=function(functionallity){
2854		if(cmMap_markersRouteLatLng.length==(cmMap_MaxWaypoints+2) && functionallity=='createRoute'){
2855			$("img",cmMap_ownDrawingButtons[functionallity].boton).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'Disabled.png');
2856		}else{
2857			$("img",cmMap_ownDrawingButtons[functionallity].boton).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'.png');
2858		}
2859	}
2860
2861    /**
2862     * Función de estilos para hacer el efecto de hover en los botones
2863     * @param {string} functionallity
2864     * @memberOf MapsApi
2865     */
2866	var cmMap_buttonHover=function(functionallity){
2867		$(cmMap_ownDrawingButtons[functionallity].boton).hover(
2868			function(){
2869				if(functionallity=='createRoute' && cmMap_markersRouteLatLng.length==(cmMap_MaxWaypoints+2) && $("img",this).attr('src')!=('/'+functionallity+'Sel.png') && $("img",this).attr('src')!=('/'+functionallity+'HoverSel.png')){
2870					$("img",this).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'Disabled.png');
2871				}else{
2872					if(cmMap_drawingMode==functionallity) {
2873						$("img",this).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'HoverSel.png');
2874					}else{
2875						$("img",this).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'Hover.png');
2876					}
2877				}
2878			},
2879			function(){
2880				if(functionallity=='createRoute' && cmMap_markersRouteLatLng.length==(cmMap_MaxWaypoints+2) && $("img",this).attr('src')!=('/'+functionallity+'Sel.png') && $("img",this).attr('src')!=('/'+functionallity+'HoverSel.png')){
2881					$("img",this).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'Disabled.png');
2882				}else{
2883					if(cmMap_drawingMode==functionallity) {
2884						$("img",this).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'Sel.png');
2885					}else{
2886						$("img",this).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'.png');
2887					}
2888				}
2889			}
2890		);
2891		
2892		$(cmMap_ownDrawingButtons[functionallity].boton).mousemove(function(){
2893			if(functionallity=='createRoute' && cmMap_markersRouteLatLng.length==(cmMap_MaxWaypoints+2) && $("img",this).attr('src')!=('/'+functionallity+'Sel.png') && $("img",this).attr('src')!=('/'+functionallity+'HoverSel.png')){
2894				$("img",this).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'Disabled.png');
2895			}else{
2896				if(cmMap_drawingMode==functionallity) {
2897					$("img",this).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'HoverSel.png');
2898				}else{
2899					$("img",this).attr('src',cmMap_rootWeb+'/edit/wizard/images/gmaps/'+functionallity+'Hover.png');
2900				}
2901			}
2902		});
2903	}
2904
2905    /**
2906     * Función para centrar en el mapa desde una dirección
2907     * @param {string} address - Dirección
2908     * @memberOf MapsApi
2909     */
2910	var cmMap_centerMapFromAddress=function(address) {
2911		cmMap_geocoder.geocode( { 'address': address}, function(results, status) {
2912			if (status == google.maps.GeocoderStatus.OK) {
2913				googleMapObject.cmMap.setCenter(results[0].geometry.location);
2914			} else {
2915				messageBox(true,resolveMessageinGmaps('{notFindAddress}'));
2916			}
2917		});
2918	}
2919
2920    /**
2921     * Función que confirma si deseamos reemplazar el marcador del mapa tras localizar una dirección
2922     * @param results
2923     * @param {string} address - Dirección
2924     * @memberOf MapsApi
2925     */
2926	var cmMap_sureDeleteMarkerFromAddress=function(results, address) {
2927		var myMessageBox = new window.top.MessageBox(300,130);
2928		myMessageBox.setMessage(resolveMessageinGmaps('{updateMarker}'));
2929		myMessageBox.addButton(window.top.resolveMessage('{lang_accept}'),function() {
2930			var _styleIdPrevMarker=cmMap_defaultIdImgMarker;
2931			for (var _idPrevMarker=0;_idPrevMarker<cmMap_overlaysInMap['markerNotInRoute'].length;_idPrevMarker++){
2932				if(cmMap_overlaysInMap['markerNotInRoute'][_idPrevMarker].visible){
2933					_styleIdPrevMarker=cmMap_overlaysInMap['markerNotInRoute'][_idPrevMarker].styleId;
2934				}
2935			}
2936			cmMap_ClearAll();
2937			googleMapObject.cmMap.setCenter(results[0].geometry.location);
2938			var marker=cmMap_createMarkerAndInfowin($.extend(cmMap_markerOptions, {icon: cmMap_markerImages[_styleIdPrevMarker].icon,shadow:cmMap_markerImages[_styleIdPrevMarker].shadow}),results[0].geometry.location,'markerNotInRoute',true,true,true,false,{'name':address,'styleId':_styleIdPrevMarker});
2939			window.top.hideLoadingLayer(document);
2940		});
2941		myMessageBox.addButton(window.top.resolveMessage('{lang_cancel}'));
2942		myMessageBox.showWindow(document);
2943	}
2944
2945    /**
2946     * Función que obtiene una dirección de un input y situa un marcador en el mapa
2947     * @param {string} address - Dirección
2948     * @memberOf MapsApi
2949     */
2950	var cmMap_placeMarkerFromAddress=function(address) {
2951		cmMap_geocoder.geocode( { 'address': address}, function(results, status) {
2952		if (status == google.maps.GeocoderStatus.OK) {
2953			if(googleMapObject.cmMap_typeParam=='location' && cmMap_contMarkerInMap > 0){
2954				cmMap_sureDeleteMarkerFromAddress(results, address);
2955				return;
2956			}
2957			googleMapObject.cmMap.setCenter(results[0].geometry.location);
2958			var marker=cmMap_createMarkerAndInfowin(cmMap_markerOptions,results[0].geometry.location,'markerNotInRoute',true,true,true,false,{'name':address});
2959		} else {
2960			messageBox(true, resolveMessageinGmaps('{notFindAddress}'));
2961		}
2962		});
2963	}
2964
2965    /**
2966     * Función obtiene una dirección de un input y situa un marcador de inicio de ruta en el mapa
2967     * @param {string} address - Dirección
2968     * @memberOf MapsApi
2969     */
2970	var cmMap_placeInitialMarkerRouteFromAddress=function(address) {
2971		cmMap_geocoder.geocode( { 'address': address}, function(results, status) {
2972			if (status == google.maps.GeocoderStatus.OK) {
2973				googleMapObject.cmMap.setCenter(results[0].geometry.location);
2974				cmMap_createRouteFromHere('','',results[0].geometry.location,false);
2975			} else {
2976				messageBox(true,resolveMessageinGmaps('{notFindAddress}'));
2977			}
2978		});
2979	}
2980
2981    /**
2982     * Función obtiene una dirección de un input y situa un marcador de fin de ruta en el mapa
2983     * @param {string} address - Dirección
2984     * @memberOf MapsApi
2985     */
2986	var cmMap_placeFinalMarkerRouteFromAddress=function(address) {
2987		cmMap_geocoder.geocode( { 'address': address}, function(results, status) {
2988			if (status == google.maps.GeocoderStatus.OK) {
2989				googleMapObject.cmMap.setCenter(results[0].geometry.location);
2990				cmMap_createRouteToHere('','',results[0].geometry.location,false);
2991			} else {
2992				messageBox(true,resolveMessageinGmaps('{notFindAddress}'));
2993			}
2994		});
2995	}
2996
2997    /**
2998     * Función para crear una ruta desde ese punto. ya sea desde un marcador ya creado como desde el valor metido en un formulario
2999     * @param {string} typeOfOverlay - Tipo del overlay
3000     * @param {string} idOverlay - Id del overlay
3001     * @param latLngForIniMarker
3002     * @param markerCreateAlready
3003     * @memberOf MapsApi
3004     */
3005	var cmMap_createRouteFromHere=function(typeOfOverlay,idOverlay,latLngForIniMarker,markerCreateAlready){
3006		cmMap_closeOldWindow();
3007		//si es el primer elemento, le situamos
3008		if(cmMap_markersRouteLatLng.length==0){
3009			cmMap_markersRouteLatLng[0]=latLngForIniMarker;
3010			cmMap_initialMarkerRoute=cmMap_createMarkerAndInfowin(cmMap_markerOptionsInRoute,cmMap_markersRouteLatLng[0],'markerInRoute',cmMap_createInfowinMarkerRoute,false,true,false,{});
3011		}else{
3012			var auxLatLng= new Array();
3013			//se borra el marker de inicio de ruta, y se pone este nuevo marcador como inicio de ruta
3014			cmMap_initialMarkerRoute.setMap(null);
3015			//se crea en la posicion uno las nuevas coordenadas
3016			auxLatLng[0]=latLngForIniMarker;
3017			cmMap_markersRouteLatLng=auxLatLng.concat(cmMap_markersRouteLatLng);
3018			cmMap_initialMarkerRoute=cmMap_createMarkerAndInfowin(cmMap_markerOptionsInRoute,cmMap_markersRouteLatLng[0],'markerInRoute',cmMap_createInfowinMarkerRoute,false,true,false,{});
3019			cmMap_generateRoute(false,true,true,true,{},0);
3020		}
3021	}
3022
3023    /**
3024     * Función para crear una ruta hasta ese punto, ya sea desde un marcador ya creado como desde el valor metido en un formulario
3025     * @param {string} typeOfOverlay - Tipo del overlay
3026     * @param {string} idOverlay - Id del overlay
3027     * @param latLngForFinMarker
3028     * @param markerCreateAlready
3029     * @memberOf MapsApi
3030     */
3031	var cmMap_createRouteToHere=function(typeOfOverlay,idOverlay,latLngForFinMarker,markerCreateAlready){
3032		cmMap_closeOldWindow();
3033		//si es el primer elemento, le situamos
3034		if(cmMap_markersRouteLatLng.length==0){
3035			cmMap_markersRouteLatLng[0]=latLngForFinMarker;
3036			cmMap_initialMarkerRoute=cmMap_createMarkerAndInfowin(cmMap_markerOptionsInRoute,cmMap_markersRouteLatLng[0],'markerInRoute',cmMap_createInfowinMarkerRoute,false,true,false,{});
3037		}else{
3038			//se crea al final del array, y se calcula la ruta
3039			var idNewMarker=cmMap_markersRouteLatLng.length;
3040			cmMap_markersRouteLatLng[idNewMarker]=latLngForFinMarker;
3041			cmMap_generateRoute(false,true,true,true,{},cmMap_overlaysInMap['markerInRoute'].length-1);
3042		}
3043	}
3044
3045    /**
3046     * Función para generar las rutas
3047     * @param openInfoWindowMarker
3048     * @param addCloseclickToMarker
3049     * @param openInfoWindowRoute
3050     * @param addCloseclickToRoute
3051     * @param dataRoute
3052     * @param positionNewElement
3053     * @memberOf MapsApi
3054     */
3055	var cmMap_generateRoute=function(openInfoWindowMarker,addCloseclickToMarker,openInfoWindowRoute,addCloseclickToRoute,dataRoute,positionNewElement){
3056		//coges las coordenadas del primer elemento por si se ha movido
3057		cmMap_markersRouteLatLng[0]=cmMap_initialMarkerRoute.getPosition();
3058		//cierras la ventana si esta abierta y giardas los datos
3059		cmMap_closeOldWindow();
3060		//eliminas el primer marcador que has puesto, porque pone uno con la ruta
3061		cmMap_initialMarkerRoute.setMap(null);
3062		cmMap_createNewRoute(openInfoWindowMarker,addCloseclickToMarker,openInfoWindowRoute,addCloseclickToRoute,dataRoute,positionNewElement);
3063	}
3064
3065    /**
3066     * Función para crear rutas. "lineas a lo largo de las calles y carreteras"
3067     * @param openInfoWindowMarker
3068     * @param addCloseclickToMarker
3069     * @param openInfoWindowRoute
3070     * @param addCloseclickToRoute
3071     * @param dataRoute
3072     * @param positionNewElement
3073     * @memberOf MapsApi
3074     */
3075	var cmMap_createNewRoute=function(openInfoWindowMarker,addCloseclickToMarker,openInfoWindowRoute,addCloseclickToRoute,dataRoute,positionNewElement) {
3076		cmMap_changeRouteByDrag=false;
3077		var waypts = [];
3078		var start= cmMap_markersRouteLatLng[0];
3079		var end=cmMap_markersRouteLatLng[cmMap_markersRouteLatLng.length-1];
3080		if(cmMap_markersRouteLatLng.length>2){
3081			for (var i = 1; i < cmMap_markersRouteLatLng.length-1; i++) {
3082				waypts.push({
3083					location:cmMap_markersRouteLatLng[i],
3084					stopover:true
3085				});
3086			}
3087		}
3088		var request = {
3089			origin:start,
3090			destination:end,
3091			waypoints: waypts,
3092			travelMode: google.maps.TravelMode.DRIVING,
3093			region: cmMap_region
3094		};
3095		cmMap_directionsService.route(request, function(result, status) {
3096			if (status == google.maps.DirectionsStatus.OK) {
3097				cmMap_directionsDisplay.setDirections(result);
3098				cmMap_directionsDisplay.setMap(googleMapObject.cmMap);
3099
3100				// Si la variable cmMap_showDirections existe y vale true, mostramos el panel de direcciones
3101				if(!googleMapObject.cmMap_editableMode && typeof(cmMap_showDirections) == 'boolean' && cmMap_showDirections) {
3102					cmMap_showDirections = false;
3103					cmMap_directionsDisplay.setPanel(cmMap_directions.get(0));
3104					$("body").addClass("cmMap_googleMapsRoute");
3105					cmMap_directions.show();
3106
3107					// Contemplamos la posibilidad de anadir opciones personalizadas despues de mostrar el panel de direcciones
3108					if(typeof(cmMap_myCustomAfterShowDirections) == 'function') {
3109						cmMap_myCustomAfterShowDirections(googleMapObject);
3110					}
3111
3112					// Le indicamos al mapa que ha sido cambiado de tamano
3113					google.maps.event.trigger(googleMapObject.cmMap, 'resize');
3114
3115					// Volvemos a centrar y establecer el zoom
3116					googleMapObject.cmMap_setCenterAndZoom();
3117				}
3118
3119				cmMap_drawMarkersInRoute(result,openInfoWindowMarker,addCloseclickToMarker);
3120				//se ha alcanzado el maximo de puntos en la ruta
3121				if(cmMap_markersRouteLatLng.length==(cmMap_MaxWaypoints+2)){
3122					googleMapObject.cmMap_container.trigger("maxWaypointReach");
3123				}
3124				
3125				//para crear una ventana de informacion en la ruta
3126				cmMap_createInfowinForRoute(cmMap_directionsDisplay,openInfoWindowRoute,addCloseclickToRoute,dataRoute)
3127				
3128			}else{
3129				if(googleMapObject.cmMap_editableMode) {
3130					messageBox(true,resolveMessageinGmaps('{incorrectAddress}'));
3131				}
3132				else {
3133					alert(resolveMessageinGmaps('{incorrectAddress}'));
3134				}
3135				//eliminamos el elemento que no deberia estar
3136				cmMap_markersRouteLatLng=cmMap_deleteElementFromArray(cmMap_markersRouteLatLng,positionNewElement);
3137			}
3138		});
3139	}
3140
3141    /**
3142     * Función para crear una ventana de informacion en la ruta
3143     * @param cmMap_directionsDisplay
3144     * @param openInfoWindowRoute
3145     * @param addCloseclickToRoute
3146     * @param dataRoute
3147     * @memberOf MapsApi
3148     */
3149	var cmMap_createInfowinForRoute=function(cmMap_directionsDisplay,openInfoWindowRoute,addCloseclickToRoute,dataRoute) {
3150		var path = cmMap_directionsDisplay.getDirections().routes[0].overview_path;
3151		var eventLine = new google.maps.Polyline({
3152			path: path,
3153			visible: true,
3154			strokeOpacity: 0,
3155			zIndex: 1000
3156		}); 
3157		eventLine.setMap(googleMapObject.cmMap);
3158		cmMap_newOverlayLatLng=path[parseInt(path.length/2)];
3159		
3160		cmMap_deleteOverlaysInMap('route');
3161		//en las rutas y marcadores en ruta siempre precargamos infowindow, porque al poder arrastrarse puede dar conflicto la siguiente vez que se crea
3162		cmMap_saveOverlayAndCreateInfowin(eventLine,'route',true,openInfoWindowRoute,addCloseclickToRoute,false,dataRoute);
3163	}
3164
3165    /**
3166     * Función que dibuja los marcadores que hemos indicado en la ruta."lineas a lo largo de las calles y carreteras"
3167     * @param directionResult
3168     * @param openInfoWindowMarker
3169     * @param addCloseclickToMarker
3170     * @memberOf MapsApi
3171     */
3172	var cmMap_drawMarkersInRoute=function(directionResult,openInfoWindowMarker,addCloseclickToMarker) {
3173		//eliminamos los marcadores y vaciamos el array
3174		//en las rutas y marcadores en ruta siempre precargamos infowindow, porque al poder arrastrarse puede dar conflicto la siguiente vez que se crea
3175		cmMap_deleteOverlaysInMap('markerInRoute');
3176		for(var j=0;j<directionResult.routes[0].legs.length;j++){
3177			var myRoute = directionResult.routes[0].legs[j];
3178			if(j==0){
3179				var marker=cmMap_createMarkerAndInfowin(cmMap_markerOptionsInRoute,myRoute.start_location,'markerInRoute',cmMap_createInfowinMarkerRoute,openInfoWindowMarker,addCloseclickToMarker,false,{});
3180				cmMap_fireEventForMarkerRoute(marker,cmMap_overlaysInMap['markerInRoute'].length-1);
3181			}
3182			marker=cmMap_createMarkerAndInfowin(cmMap_markerOptionsInRoute,myRoute.end_location,'markerInRoute',cmMap_createInfowinMarkerRoute,openInfoWindowMarker,addCloseclickToMarker,false,{});
3183			cmMap_fireEventForMarkerRoute(marker,cmMap_overlaysInMap['markerInRoute'].length-1);
3184		}
3185	}
3186
3187    /**
3188     * Función que lanza un evento para los marcadores de la ruta
3189     * @param m
3190     * @param idMarker
3191     * @memberOf MapsApi
3192     */
3193	var cmMap_fireEventForMarkerRoute=function(m,idMarker){
3194		google.maps.event.addListener(m, 'dragend', function(event) {
3195			//cierras las ventanas antes de mover la ruta
3196			cmMap_closeOldWindow();
3197			cmMap_dragEventMarkerInRoute(this,idMarker);
3198		});
3199	}
3200
3201    /**
3202     * Función para que la ruta se mueva al mover un marcador
3203     * @param el
3204     * @param {string} id - Id
3205     * @memberOf MapsApi
3206     */
3207	var cmMap_dragEventMarkerInRoute=function(el,id){
3208		cmMap_deleteOverlaysInMap('markerInRoute');
3209		//coges las coordenadas del primer elemento por si se ha movido
3210		cmMap_markersRouteLatLng[id]=el.getPosition();
3211		if(id==0)cmMap_initialMarkerRoute.setPosition(el.getPosition());
3212		cmMap_createNewRoute(false,false,false,true,{},id);
3213	}
3214
3215    /**
3216     * Función que borra todos los marcadores de la ruta
3217     * @param typeOfOverlay
3218     * @memberOf MapsApi
3219     */
3220	var cmMap_deleteOverlaysInMap=function(typeOfOverlay){
3221		for(var i=0;i<cmMap_overlaysInMap[typeOfOverlay].length;i++){
3222			cmMap_overlaysInMap[typeOfOverlay][i].overlay.setMap(null);
3223		}
3224		cmMap_overlaysInMap[typeOfOverlay]=[];
3225	}
3226
3227    /**
3228     * Función para crear rutas a partir de los markers que existan en el mapa (hasta los 10 primeros)
3229     * @memberOf MapsApi
3230     */
3231	var cmMap_createNewRouteFromMarkers=function() {
3232
3233		// Si no tenemos al menos dos puntos no podemos calcular la ruta
3234		if(cmMap_overlaysInMap['markerNotInRoute'].length < 2) return;
3235
3236		cmMap_changeRouteByDrag=false;
3237		var waypts = [];
3238		var start = cmMap_overlaysInMap['markerNotInRoute'][0].overlay.getPosition();
3239		var end=cmMap_overlaysInMap['markerNotInRoute'][cmMap_overlaysInMap['markerNotInRoute'].length-1].overlay.getPosition();
3240		if(cmMap_overlaysInMap['markerNotInRoute'].length>2){
3241			for (var i = 1; i < cmMap_overlaysInMap['markerNotInRoute'].length-1; i++) {
3242				// Si tenemos mas de 8 puntos intermedios no seguimos, el limite es 10
3243				if(i > 8) break;
3244				waypts.push({
3245					location:cmMap_overlaysInMap['markerNotInRoute'][i].overlay.getPosition(),
3246					stopover:true
3247				});
3248			}
3249		}
3250		var request = {
3251			origin:start,
3252			destination:end,
3253			waypoints: waypts,
3254			travelMode: google.maps.TravelMode.DRIVING,
3255			region: cmMap_region
3256		};
3257		cmMap_directionsService.route(request, function(result, status) {
3258			if (status == google.maps.DirectionsStatus.OK) {
3259				cmMap_directionsDisplay.setDirections(result);
3260				cmMap_directionsDisplay.setMap(googleMapObject.cmMap);
3261
3262				// Si la variable cmMap_showDirections existe y vale true, mostramos el panel de direcciones
3263				if(!googleMapObject.cmMap_editableMode && typeof(cmMap_showDirections) == 'boolean' && cmMap_showDirections) {
3264					cmMap_showDirections = false;
3265					cmMap_directionsDisplay.setPanel(cmMap_directions.get(0));
3266					$("body").addClass("cmMap_googleMapsRoute");
3267					cmMap_directions.show();
3268
3269					// Contemplamos la posibilidad de anadir opciones personalizadas despues de mostrar el panel de direcciones
3270					if(typeof(cmMap_myCustomAfterShowDirections) == 'function') {
3271						cmMap_myCustomAfterShowDirections(googleMapObject);
3272					}
3273
3274					// Le indicamos al mapa que ha sido cambiado de tamano
3275					google.maps.event.trigger(googleMapObject.cmMap, 'resize');
3276
3277					// Volvemos a centrar y establecer el zoom
3278					googleMapObject.cmMap_setCenterAndZoom();
3279				}
3280
3281			}
3282		});
3283	}
3284
3285    /**
3286     * Función que situar un marcador en el  mapa y la ventana de informacion asociada a el
3287     * @param markerOptions
3288     * @param position
3289     * @param typeOfOverlay
3290     * @param createInfoWindow
3291     * @param openInfoWindowMarker
3292     * @param addCloseclickToMarker
3293     * @param createdFromKml
3294     * @param dataOverlay
3295     * @memberOf MapsApi
3296     */
3297	var cmMap_createMarkerAndInfowin=function(markerOptions,position,typeOfOverlay,createInfoWindow,openInfoWindowMarker,addCloseclickToMarker,createdFromKml,dataOverlay){
3298		cmMap_saveOverlayAndCreateInfowin(new google.maps.Marker(markerOptions),typeOfOverlay,createInfoWindow,openInfoWindowMarker,addCloseclickToMarker,createdFromKml,dataOverlay);
3299		var currentMarker = cmMap_overlaysInMap[typeOfOverlay];
3300		var markerToPlace=currentMarker[currentMarker.length-1].overlay;
3301		markerToPlace.setMap(googleMapObject.cmMap);
3302		markerToPlace.setPosition(position);
3303		
3304		//en modo no editable (modo usuario), guardamos en el array de marcadores por categorias los marcadores que se utilizan
3305		if(!googleMapObject.cmMap_editableMode && typeOfOverlay=='markerNotInRoute'){
3306			if(!cmMap_MarkersInMapByCategory[dataOverlay['styleId']]){
3307				cmMap_MarkersInMapByCategory[dataOverlay['styleId']]=new Array();
3308			}
3309			cmMap_MarkersInMapByCategory[dataOverlay['styleId']].push(markerToPlace);
3310		}
3311		
3312		//si tenemos un icono asignado, se lo ponemos
3313		if(typeOfOverlay=='markerNotInRoute'){
3314			if(currentMarker[currentMarker.length-1] && currentMarker[currentMarker.length-1].styleId!=''){
3315				markerToPlace.setIcon(cmMap_markerImages[currentMarker[currentMarker.length-1].styleId].icon);
3316				markerToPlace.setShadow(cmMap_markerImages[currentMarker[currentMarker.length-1].styleId].shadow);
3317			}
3318		}
3319
3320		//indicamos si estamos en modo edicion tipo localizacion que se ha alcanzado el maximo de marcadores (1)
3321		if(googleMapObject.cmMap_editableMode && googleMapObject.cmMap_typeParam=='location'){
3322			googleMapObject.cmMap_container.trigger('maxPointReach');
3323		}
3324		
3325		return markerToPlace;
3326	}
3327
3328    /**
3329     * Función que guarda en el array y crea ventana de información en los overlays creados del drawingmanager o el kml
3330     * @param newOverlay - Nuevo overlay
3331     * @param typeOfOverlay - Tipo de overlay
3332     * @param createInfoWindow
3333     * @param openWindowInfo
3334     * @param addCloseclick
3335     * @param createdFromKml
3336     * @param dataOverlay
3337     * @memberOf MapsApi
3338     */
3339	var cmMap_saveOverlayAndCreateInfowin=function(newOverlay,typeOfOverlay,createInfoWindow,openWindowInfo,addCloseclick,createdFromKml,dataOverlay) {
3340		var array=new Array();
3341		cmMap_overlaysInMap[typeOfOverlay].push(array);
3342		var id=cmMap_overlaysInMap[typeOfOverlay].length-1;
3343		cmMap_overlaysInMap[typeOfOverlay][id].overlay = newOverlay;
3344		cmMap_overlaysInMap[typeOfOverlay][id].visible = true;
3345		cmMap_overlaysInMap[typeOfOverlay][id].name = (dataOverlay['name']==undefined)?'':dataOverlay['name'];
3346		cmMap_overlaysInMap[typeOfOverlay][id].description = (dataOverlay['description']==undefined)?'':dataOverlay['description'];
3347		cmMap_overlaysInMap[typeOfOverlay][id].url = (dataOverlay['url']==undefined)?'':dataOverlay['url'];
3348		cmMap_overlaysInMap[typeOfOverlay][id].idContent = (dataOverlay['idContent']==undefined)?'':dataOverlay['idContent'];
3349		cmMap_overlaysInMap[typeOfOverlay][id].alias = (dataOverlay['alias']==undefined)?'':dataOverlay['alias'];
3350		cmMap_overlaysInMap[typeOfOverlay][id].content = (dataOverlay['content']==undefined)?'':dataOverlay['content'];
3351		cmMap_overlaysInMap[typeOfOverlay][id].styleId = (dataOverlay['styleId']==undefined)?'':dataOverlay['styleId'];
3352		
3353		if(typeOfOverlay=='markerNotInRoute'){
3354			cmMap_overlaysInMap[typeOfOverlay][id].clickForRouteFromHere=false;
3355			cmMap_overlaysInMap[typeOfOverlay][id].clickForRouteToHere=false;
3356			cmMap_overlaysInMap[typeOfOverlay][id].overlay.setTitle(cmMap_overlaysInMap[typeOfOverlay][id].name);
3357		}
3358		//indicamos si queremos crear ventana
3359		if(createInfoWindow){
3360			if(createdFromKml){
3361				cmMap_setInfowinToOverlayFromKml(typeOfOverlay,id,openWindowInfo,addCloseclick);
3362			}else{
3363				cmMap_setInfowin(typeOfOverlay,id,openWindowInfo,addCloseclick);
3364			}
3365		}
3366	}
3367
3368    /**
3369     * Función que crea una ventana cuando hacemos click (para cuando cargamos elementos desde el kml)
3370     * @param {string} typeOfOverlay - Tipo de overlay
3371     * @param {string} idOverlay - Id
3372     * @param openWindowInfo
3373     * @param addCloseclick
3374     * @memberOf MapsApi
3375     */
3376	var cmMap_setInfowinToOverlayFromKml=function(typeOfOverlay,idOverlay,openWindowInfo,addCloseclick){
3377		var overlayToAttach=cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay;
3378		google.maps.event.addListenerOnce(overlayToAttach, 'click', function(event) {
3379			cmMap_setInfowin(typeOfOverlay,idOverlay,openWindowInfo,addCloseclick);
3380			cmMap_openInfowinWhenClick(typeOfOverlay,idOverlay,event);
3381		});
3382	}
3383
3384    /**
3385     * Función que crea el contenido, lo asocia a la ventana, crea la ventana si no estaba creada, y asocia la ventana a un marcador
3386     * @param {string} typeOfOverlay - Tipo de overlay
3387     * @param {string} idOverlay - Id
3388     * @param openWindowInfo
3389     * @param addCloseclick
3390     * @memberOf MapsApi
3391     */
3392	var cmMap_setInfowin=function(typeOfOverlay,idOverlay,openWindowInfo,addCloseclick){
3393		var windowInfoCreateAlready=cmMap_createInfowin(typeOfOverlay,idOverlay);
3394		//si se ha indicado que se abriera la ventana, si el elemento ya se habia creado, no la abrimos.
3395		if(openWindowInfo)openWindowInfo=!windowInfoCreateAlready;
3396		//si se ha indicado que el evento closeclick se puede asignar, si el elemento ya se habia creado, no lo asignamos
3397		if(addCloseclick)addCloseclick=!windowInfoCreateAlready;
3398		cmMap_attachClickToOverlay(typeOfOverlay,idOverlay);
3399		if(addCloseclick){cmMap_attachCloseclickToInfowin(typeOfOverlay,idOverlay);}
3400		if(openWindowInfo){cmMap_openInfowinJustCreated(typeOfOverlay,idOverlay);}
3401	}
3402
3403    /**
3404     * Función que crea una ventana de información para el marcador
3405     * @param {string} typeOfOverlay - Tipo de overlay
3406     * @param {string} id - Id
3407     * @returns {boolean}
3408     * @memberOf MapsApi
3409     */
3410	var cmMap_createInfowin=function(typeOfOverlay,id){
3411		//cuando estamos posicionando el marcador de una ruta, puede que ya hubiese informacion asociada
3412		if(!cmMap_infoWindowInMap[typeOfOverlay][id]){
3413			cmMap_infoWindowInMap[typeOfOverlay][id] = new Array();
3414			cmMap_infoWindowInMap[typeOfOverlay][id].infoWindow = new google.maps.InfoWindow();
3415			if(cmMap_maxWidthInfoWindow != 'auto') {
3416				cmMap_infoWindowInMap[typeOfOverlay][id].infoWindow.setOptions({ maxWidth: cmMap_maxWidthInfoWindow });
3417			}
3418
3419			return false;
3420		}
3421		return true;
3422	}
3423
3424    /**
3425     * Función que carga el contenido del marcador en la ventana. Si esta vacio solo sale el formulario
3426     * @param {string} typeOfOverlay - Tipo de overlay
3427     * @param {string} id - Id
3428     * @returns {string}
3429     * @memberOf MapsApi
3430     */
3431	var cmMap_createContentInfowin=function(typeOfOverlay,id){
3432		var contentInfoWindow='';
3433		var currentOverlay = cmMap_overlaysInMap[typeOfOverlay][id];
3434		//si estamos en modo edicion
3435		if(googleMapObject.cmMap_editableMode){
3436			switch(typeOfOverlay){
3437				case 'polyline': case 'polygon': case 'rectangule': case 'circle':
3438					var color, colorName;
3439					if(currentOverlay && currentOverlay.styleId){
3440						color=cmMap_overlayColors[currentOverlay.styleId].strokeC;
3441						colorName=cmMap_overlayColors[currentOverlay.styleId].name;
3442					}else{
3443						color=cmMap_overlayColors[cmMap_defaultIdColor].strokeC;
3444						colorName=cmMap_overlayColors[cmMap_defaultIdColor].name;
3445					}
3446					contentInfoWindow+= '<div class="infoWindowOverlay infoWindowOtherOverlay">';
3447					if(typeOfOverlay=="polyline"){
3448						contentInfoWindow+= '<div class="infoWindowTitle">'+resolveMessageinGmaps('{lineInfo}')+'</div>';
3449					}else if(typeOfOverlay=="polygon"){
3450						contentInfoWindow+= '<div class="infoWindowTitle">'+resolveMessageinGmaps('{areaInfo}')+'</div>';
3451					}else{
3452						contentInfoWindow+= '<div class="infoWindowTitle">'+resolveMessageinGmaps('{elementInfo}')+'</div>';
3453					}
3454					contentInfoWindow+= '<div class="infoWindowStyleInfo"></div>';
3455				break;
3456				case 'markerInRoute':
3457					contentInfoWindow+= '<div class="infoWindowOverlay infoWindowMarkerInRoute">';
3458				break;
3459				case 'markerNotInRoute':
3460					if(currentOverlay && currentOverlay.styleId){
3461						var imgIcon=cmMap_markerImages[currentOverlay.styleId];
3462					}else{
3463						var imgIcon=cmMap_markerImages[cmMap_defaultIdImgMarker];
3464					}
3465					contentInfoWindow+= '<div class="infoWindowOverlay infoWindowMarkerNotInRoute infoWindowOverlay'+googleMapObject.cmMap_typeParam+'">';
3466					contentInfoWindow+= '<div class="infoWindowTitle">'+resolveMessageinGmaps('{markerInfo}')+'</div>';
3467					contentInfoWindow+= '<div class="infoWindowStyleInfo"></div>';
3468				break;
3469				case 'route':
3470					contentInfoWindow+= '<div class="infoWindowOverlay infoWindowRoute">';
3471					contentInfoWindow+= '<div class="infoWindowTitle">'+resolveMessageinGmaps('{routeByCarInfo}')+'</div>';
3472				break;
3473				default:
3474			}
3475			
3476			contentInfoWindow+= '<div class="infoWindowContent">';
3477			
3478			switch(typeOfOverlay){
3479				case 'polyline': case 'polygon': case 'rectangule': case 'circle':
3480					contentInfoWindow+= '<div class="infoWindowStyleLink"><div class="colorOverlayToShow" style="background-color:'+color+'" title="'+colorName+'"></div></div>';
3481				break;
3482				case 'markerNotInRoute':
3483					contentInfoWindow+= '<div class="infoWindowStyleLink"><img src="'+imgIcon.markerIcon+'" title="'+imgIcon.name+'" width="'+imgIcon.icon["size"].width+'" height="'+imgIcon.icon["size"].height+'"'+((imgIcon.icon["size"].height<40)?' style="margin-top:'+parseInt((40-imgIcon.icon["size"].height)/2,10)+'px;"':'')+'/></div>';
3484				break;
3485				case 'route':case 'markerInRoute':
3486				break;
3487				default:
3488			}
3489			
3490			switch(typeOfOverlay){
3491				case 'polyline': case 'polygon': case 'rectangule': case 'circle': case 'markerNotInRoute': case 'route':
3492					var showLinkUrl = (currentOverlay && currentOverlay.url == '' && currentOverlay.idContent != '' && currentOverlay.alias != '')?false:true;
3493					contentInfoWindow+= '<form id="infoWindowForm" action="">';
3494					//si estamos en tipo localizacion estos campos no se muestran
3495					if(googleMapObject.cmMap_typeParam!='location'){
3496						contentInfoWindow+='<div class="infoWindowFormContainer">\n';
3497						contentInfoWindow+='	<div class="infoWindowFormCol1">\n';
3498						contentInfoWindow+='		<div class="infoWindowFormField infoWindowName">\n';
3499						contentInfoWindow+='			<span class="infoWindowLabel">'+resolveMessageinGmaps('{title}')+': </span>\n';
3500						contentInfoWindow+='			<input name="name" id="name" type="text" value="'+((currentOverlay)?currentOverlay.name:"")+'" />\n';
3501						contentInfoWindow+='		</div>';
3502						contentInfoWindow+='		<div class="infoWindowFormField infoWindowUrl">\n';
3503						contentInfoWindow+='			<div class="linkTypeContainer">\n';
3504						contentInfoWindow+='				<input type="radio" class="formradio"'+((showLinkUrl)?' checked="checked"':'')+' id="linkType_url" name="linkType" onclick="changeLinkType(this);"/>\n';
3505						contentInfoWindow+='				<label for="linkType_url" class="infoWindowLabel">'+resolveMessageinGmaps('{url}')+'</label>\n';
3506						contentInfoWindow+='				<input type="radio" class="formradio"'+((!showLinkUrl)?' checked="checked"':'')+' id="linkType_content" name="linkType" onclick="changeLinkType(this);"/>\n';
3507						contentInfoWindow+='				<label for="linkType_content" class="infoWindowLabel">'+resolveMessageinGmaps('{content}')+'</label>\n';
3508						contentInfoWindow+='			</div>\n';
3509						contentInfoWindow+='			<div class="linkContainer">\n';
3510						contentInfoWindow+='				<div id="linkUrl"'+((!showLinkUrl)?' style="display: none;"':'')+'>\n';
3511						contentInfoWindow+='					<input name="linkText_url" id="linkText_url" type="text" maxlength="512" value="'+((currentOverlay && currentOverlay.url && currentOverlay.url != '')?currentOverlay.url:"")+'" />\n';
3512						contentInfoWindow+='				</div>\n';
3513						contentInfoWindow+='				<div id="linkContent"'+((showLinkUrl)?' style="display: none;"':'')+'>\n';
3514						contentInfoWindow+='					<input name="linkText_content" id="linkText_content" type="text" maxlength="512" disabled="disabled" value="'+((currentOverlay && currentOverlay.content && currentOverlay.content != '')?currentOverlay.content:resolveMessageinGmaps('{noContent}'))+'" />\n';
3515						contentInfoWindow+='					<input name="link_idContent" id="link_idContent" type="hidden" value="'+((currentOverlay && currentOverlay.idContent && currentOverlay.idContent != '')?currentOverlay.idContent:"")+'" />\n';
3516						contentInfoWindow+='					<input name="link_alias" id="link_alias" type="hidden" value="'+((currentOverlay && currentOverlay.alias && currentOverlay.alias != '')?currentOverlay.alias:"")+'" />\n';
3517						contentInfoWindow+='					<button type="button" class="updateButton" id="lookForcontent" onclick="openSearchWindow();">...</button>\n';
3518						contentInfoWindow+='					<button type="button" class="updateButton" id="delContent" onclick="cmMap_deleteContent();">&times;</button>\n';
3519						contentInfoWindow+='				</div>\n';
3520						contentInfoWindow+='			</div>\n';
3521						contentInfoWindow+='		</div>\n';
3522						contentInfoWindow+='	</div>\n';
3523						contentInfoWindow+='	<div class="infoWindowFormCol2">\n';
3524						contentInfoWindow+='		<div class="infoWindowFormField infoWindowDescription">\n';
3525						contentInfoWindow+='			<span class="infoWindowLabel">'+resolveMessageinGmaps('{description}')+': </span>\n';
3526						contentInfoWindow+='			<textarea name="description" id="description">'+((currentOverlay)?currentOverlay.description:"")+'</textarea>\n';
3527						contentInfoWindow+='		</div>\n';
3528						contentInfoWindow+='	</div>\n';
3529						contentInfoWindow+='</div>\n';
3530					}
3531					contentInfoWindow+='<input name="id_overlay" id="id_overlay" type="hidden" value="'+id+'"/>';
3532					if(typeOfOverlay == 'markerNotInRoute'){
3533						contentInfoWindow+='<input name="styleId" id="styleId" type="hidden" value="'+((currentOverlay.styleId!='')?currentOverlay.styleId:cmMap_defaultIdImgMarker)+'" />';
3534					}else{
3535						contentInfoWindow+='<input name="styleId" id="styleId" type="hidden" value="'+((currentOverlay.styleId!='')?currentOverlay.styleId:cmMap_defaultIdColor)+'" />';
3536					}
3537					contentInfoWindow+='<input name="typeOfOverlay" id="typeOfOverlay" type="hidden" value="'+typeOfOverlay+'" />';
3538					contentInfoWindow+='<div class="infoWindowFormButton">';
3539					if(typeOfOverlay == 'markerNotInRoute'){
3540						if(cmMap_markersRouteLatLng.length<(cmMap_MaxWaypoints+2) && googleMapObject.cmMap_createRoutesMode){
3541							contentInfoWindow+='<div class="infoWindowLinks">';
3542							if(currentOverlay.clickForRouteFromHere==false){contentInfoWindow+='<a class="createMarkerRoute routeFromHere" href="javascript:;">'+resolveMessageinGmaps('{directionsFromHere}')+'</a>';}
3543							if(currentOverlay.clickForRouteToHere==false){contentInfoWindow+='<a class="createMarkerRoute routeToHere" href="javascript:;">'+resolveMessageinGmaps('{directionsToHere}')+'</a>';}
3544							contentInfoWindow+='</div>';
3545						}
3546					}
3547					if(typeOfOverlay=='route'){
3548						contentInfoWindow+='<button type="button" class="updateButton deleteRoute">'+resolveMessageinGmaps('{deleteRoute}')+'</button>';
3549					}else{
3550						contentInfoWindow+='<button type="button" class="updateButton deleteOverlay deleteOverlayButton">'+resolveMessageinGmaps('{delete}')+'</button>';
3551					}
3552					contentInfoWindow+=' <button type="submit" class="updateButton saveOverlay" id="infoWindowSaveButton">'+resolveMessageinGmaps('{save}')+'</button>';
3553					contentInfoWindow+=' <button type="button" class="updateButton cancelChanges">'+resolveMessageinGmaps('{cancel}')+'</button>';
3554					contentInfoWindow+='</div>';
3555					contentInfoWindow+='</form>';
3556				break;
3557				case 'markerInRoute':
3558					contentInfoWindow+= '<form id="infoWindowForm" action="">';
3559					contentInfoWindow+='<input name="id_overlay" id="id_overlay" type="hidden" value="'+id+'"/>';
3560					contentInfoWindow+='<input name="typeOfOverlay" id="typeOfOverlay" type="hidden" value="'+typeOfOverlay+'" />';
3561					contentInfoWindow+='</form>';
3562					contentInfoWindow+='<div class="infoWindowFormButton markerInRouteDeleteLink">';
3563					contentInfoWindow+='<button type="button" class="updateButton deleteOverlay deletePointButton">'+resolveMessageinGmaps('{deleteRoutePoint}')+'</button> ';
3564					contentInfoWindow+='<button type="button" class="updateButton deleteRoute">'+resolveMessageinGmaps('{deleteRoute}')+'</button>';
3565					contentInfoWindow+='</div>';
3566				break;
3567				default:
3568			}
3569
3570			contentInfoWindow+='</div>';
3571			contentInfoWindow+='</div>';
3572		}else{
3573			//si no estamos en modo edicion
3574			contentInfoWindow+= '<div class="infoWindowOverlayToShow">';
3575			contentInfoWindow+= '<div class="infoWindowContent">';
3576			switch(typeOfOverlay){
3577				case 'polyline': case 'polygon': case 'rectangule': case 'circle': case 'markerNotInRoute': case 'route':
3578				if(currentOverlay){
3579					if(  currentOverlay.name != '' ||
3580						 currentOverlay.description != '' ||
3581						(currentOverlay.url && currentOverlay.url != '')){
3582
3583						contentInfoWindow+='<div class="infoWindowFormContainer">';
3584
3585						if(currentOverlay.name!=''){
3586							contentInfoWindow+='<div class="infoWindowFormField infoWindowName"><span class="nameInInfoWindow">'+currentOverlay.name+'</span></div>';
3587						}
3588						if(currentOverlay.description!=''){
3589							contentInfoWindow+='<div class="infoWindowFormField infoWindowDescription"><span class="descriptionInInfoWindow">'+$.trim(currentOverlay.description).replace(/\n\n/g,"\n").replace(/\n/g,"<br/>")+'</span></div>';
3590						}
3591						
3592						// Si tenemos enlace lo procesamos e insertamos el enlace al marcador
3593						var finalUrl = (currentOverlay.url && currentOverlay.url != '')?currentOverlay.url:'';
3594
3595						var hasUrl = finalUrl != '';
3596						var hasHowToArrive = typeOfOverlay=='markerNotInRoute' && cmMap_howToArrive && !cmMap_showForm;
3597
3598						if(hasUrl || hasHowToArrive) {
3599							contentInfoWindow+='<div class="infoWindowFormField infoWindowUrl">';
3600							if(finalUrl != '') {
3601								// Si es un enlace externo hacemos que el enlace se abra en una ventana nueva
3602								var targetUrl = '';
3603								if(finalUrl.indexOf('http://') != -1 || finalUrl.indexOf('https://') != -1) {
3604									targetUrl = '_blank';
3605								}
3606								contentInfoWindow+='<span class="urlInInfoWindow"><a href="'+finalUrl+'"'+((targetUrl!='')?' target="'+targetUrl+'"':'')+'>'+resolveMessageinGmaps('{readMore}')+'</a></span>';
3607							}
3608							if(hasHowToArrive){
3609								contentInfoWindow+='<span class="howToArriveInfoWindow"><a href="#">'+resolveMessageinGmaps('{directions}')+'</a></span>';
3610							}
3611							contentInfoWindow+='</div>';
3612						}
3613
3614						contentInfoWindow+='</div>';
3615					}
3616				}
3617				break;
3618				default:
3619			}
3620			contentInfoWindow+='</div>';
3621			contentInfoWindow+='</div>';
3622		}
3623		return contentInfoWindow;
3624	}
3625
3626    /**
3627     * Función que asocia el contenido a una ventana
3628     * @param {string} typeOfOverlay - Tipo de overlay
3629     * @param {string} id - Id
3630     * @param text
3631     * @memberOf MapsApi
3632     */
3633	var cmMap_setContentInfowin=function(typeOfOverlay,id,text){
3634		cmMap_infoWindowInMap[typeOfOverlay][id].infoWindow.setContent(text);
3635	}
3636
3637    /**
3638     * Función que abre la ventana al hacer click
3639     * @param {string} typeOfOverlay - Tipo de overlay
3640     * @param {string} id - Id
3641     * @param {string} evento - Evento
3642     * @memberOf MapsApi
3643     */
3644	var cmMap_openInfowinWhenClick=function(typeOfOverlay,id,evento){
3645		//si no es un marcador sino el otro tipo de superposiciones, hay que situarlo en el mapa
3646		if(typeOfOverlay!='markerInRoute' && typeOfOverlay!='markerNotInRoute'){
3647			cmMap_infoWindowInMap[typeOfOverlay][id].infoWindow.setPosition(evento.latLng);
3648		}
3649		//si no estamos en modo editable, solo se abre la ventana si hay informacion
3650		if( googleMapObject.cmMap_editableMode ||
3651			cmMap_overlaysInMap[typeOfOverlay][id].name != '' ||
3652			cmMap_overlaysInMap[typeOfOverlay][id].description != '' ||
3653			(cmMap_overlaysInMap[typeOfOverlay][id].url && cmMap_overlaysInMap[typeOfOverlay][id].url != '') ||
3654			(cmMap_overlaysInMap[typeOfOverlay][id].idContent != '' && cmMap_overlaysInMap[typeOfOverlay][id].alias != '')){
3655			cmMap_openInfowin(typeOfOverlay,id);
3656		}
3657	}
3658
3659    /**
3660     * Función que asocia el evento de click a un marcador para abrir una ventana
3661     * @param {string} typeOfOverlay - Tipo de overlay
3662     * @param {string} id - Id
3663     * @memberOf MapsApi
3664     */
3665	var cmMap_attachClickToOverlay=function(typeOfOverlay,id){
3666		var overlayToAttach=cmMap_overlaysInMap[typeOfOverlay][id].overlay;
3667		
3668		google.maps.event.addListener(overlayToAttach, 'click', function(event) {
3669			cmMap_openInfowinWhenClick(typeOfOverlay,id,event)
3670		});
3671	}
3672
3673    /**
3674     * Función que asocia el evento de closeclick a una ventana
3675     * @param {string} typeOfOverlay - Tipo de overlay
3676     * @param {string} id - Id
3677     * @memberOf MapsApi
3678     */
3679	var cmMap_attachCloseclickToInfowin=function(typeOfOverlay,id){
3680		google.maps.event.addListener(cmMap_infoWindowInMap[typeOfOverlay][id].infoWindow, 'closeclick', function() {
3681			if(googleMapObject.cmMap_editableMode){cmMap_saveFromFormInfowin($("#infoWindowForm"));}
3682			//no hay ventana que cerrar, lo ponemos a null
3683			cmMap_oldInfoWindow=null;
3684		});
3685	}
3686
3687    /**
3688     * Si el marcador se acaba de crear, la ventana se abre directamente (en las rutas puede que no se acabe de crear)
3689     * @param {string} typeOfOverlay - Tipo de overlay
3690     * @param {string} id - Id
3691     * @memberOf MapsApi
3692     */
3693	var cmMap_openInfowinJustCreated=function(typeOfOverlay,id){
3694		//se abre la ventana nada mas crear, si es la primera vez que se crea.
3695		//suele pasar que no se la primera vez cuando es una ruta
3696		if(typeOfOverlay!='markerInRoute' && typeOfOverlay!='markerNotInRoute'){
3697			//si no es un marcador sino el otro tipo de superposiciones, hay que situarlo en el mapa
3698			if(cmMap_newOverlayLatLng!='')cmMap_infoWindowInMap[typeOfOverlay][id].infoWindow.setPosition(cmMap_newOverlayLatLng);
3699		}
3700		cmMap_openInfowin(typeOfOverlay,id);
3701	}
3702
3703    /**
3704     * Función que abre la ventana asociada a un marcador y carga el javascript necesario
3705     * @param {string} typeOfOverlay - Tipo de overlay
3706     * @param {string} id - Id
3707     * @memberOf MapsApi
3708     */
3709	var cmMap_openInfowin=function(typeOfOverlay,id){
3710		var m=cmMap_overlaysInMap[typeOfOverlay][id].overlay;
3711		cmMap_closeOldWindow();
3712		cmMap_oldInfoWindow = cmMap_infoWindowInMap[typeOfOverlay][id].infoWindow;
3713		cmMap_oldInfoWindow.setContent(cmMap_createContentInfowin(typeOfOverlay,id));
3714		if(typeOfOverlay!='markerInRoute' && typeOfOverlay!='markerNotInRoute'){
3715			cmMap_oldInfoWindow.open(googleMapObject.cmMap);
3716		}else{
3717			cmMap_oldInfoWindow.open(googleMapObject.cmMap, m);
3718		}
3719		if($("div.infoWindowOverlay").length > 0) $("div.infoWindowOverlay").parent().css({overflow:'hidden'});
3720		window.setTimeout(function() {cmMap_loadInfowinScript(typeOfOverlay,id)},500);
3721	}
3722
3723    /**
3724     * Función que guarda la informacion de la ventana abierta y la cierra
3725     * @memberOf MapsApi
3726     */
3727	var cmMap_closeOldWindow=function(){
3728		if(cmMap_oldInfoWindow) {
3729			if(googleMapObject.cmMap_editableMode){cmMap_saveFromFormInfowin($("#infoWindowForm"));}
3730			cmMap_oldInfoWindow.close();
3731			cmMap_oldInfoWindow=null;
3732		}
3733	}
3734
3735    /**
3736     * Función que carga los scripts necesarios para la ventana de información
3737     * @param {string} typeOfOverlay - Tipo de overlay
3738     * @param {string} idOverlay - Id
3739     * @memberOf MapsApi
3740     */
3741	var cmMap_loadInfowinScript=function(typeOfOverlay,idOverlay){
3742		if(googleMapObject.cmMap_editableMode){
3743			var container =$('div.infoWindowOverlay');
3744			var infoWindowStyleLink=$("div.infoWindowStyleLink",container);
3745			var infoWindowStyleInfo=$("div.infoWindowStyleInfo",container);
3746			var infoWindowContent=$("div.infoWindowContent",container);
3747			
3748			//eliminar un overlay del mapa
3749			$("button.deleteOverlay",container).click(function(){
3750				cmMap_deleteAOverlayInMap(typeOfOverlay,idOverlay);
3751				return false;
3752			});
3753			
3754			//no guarda los cambios de la ventana de info
3755			$('button.cancelChanges',container).click(function(){
3756				cmMap_cancelChangesFromInfowin(typeOfOverlay,idOverlay);
3757				return false;
3758			});
3759			
3760			$('form#infoWindowForm',container).submit(function(){
3761				cmMap_saveFromFormAndCloseInfowin();
3762				return false;
3763			});
3764			
3765			switch(typeOfOverlay){
3766				case 'polyline': case 'polygon': case 'rectangule': case 'circle':
3767					if(cmMap_overlayColorsLength > 1) {
3768						cmMap_colorSelector(typeOfOverlay,idOverlay);
3769					}
3770				break;
3771				case 'markerNotInRoute':
3772					if(cmMap_markerImagesLength > 1) {
3773						cmMap_imgSelector(typeOfOverlay,idOverlay);
3774					}
3775					
3776					$("a.routeFromHere",container).click(function(){
3777						//indicamos que hemos hecho click en crear ruta
3778						cmMap_overlaysInMap[typeOfOverlay][idOverlay].clickForRouteFromHere=true;
3779						cmMap_createRouteFromHere(typeOfOverlay,idOverlay,cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.getPosition(),true);
3780						return false;
3781					});
3782					
3783					$("a.routeToHere",container).click(function(){
3784						cmMap_overlaysInMap[typeOfOverlay][idOverlay].clickForRouteToHere=true;
3785						cmMap_createRouteToHere(typeOfOverlay,idOverlay,cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.getPosition(),true)
3786						return false;
3787					});
3788				break;
3789				case 'markerInRoute': case 'route':
3790					//eliminar un overlay del mapa
3791					$("button.deleteRoute",container).click(function(){
3792						cmMap_deleteRouteInMap();
3793						return false;
3794					});
3795				break;
3796				default:
3797			}
3798		}else{
3799			$("div.infoWindowOverlayToShow span.howToArriveInfoWindow a").click(function(){
3800				showHowToArrive(typeOfOverlay,idOverlay);
3801				return false;
3802			});
3803
3804			// Si tenemos alguna funcion personalizada a nivel de proyecto que quiera
3805			// realizar alguna terea alternativa una vez abierto un infoWindow, la llamamos...
3806			if(typeof(cmMap_customAfterOpenInfoWindow) == 'function' && cmMap_oldInfoWindow) {
3807				cmMap_customAfterOpenInfoWindow(googleMapObject, cmMap_oldInfoWindow, null);
3808			}
3809
3810		}
3811	}
3812
3813    /**
3814     * Función que no guarda los datos cambiados en el formulario
3815     * @param {string} typeOfOverlay - Tipo de overlay
3816     * @param {string} idOverlay - Id
3817     * @memberOf MapsApi
3818     */
3819	var cmMap_cancelChangesFromInfowin=function(typeOfOverlay,idOverlay){
3820		//si es un marcador o un poligono volvemos a poner su color original
3821		switch(typeOfOverlay){
3822			case 'polyline':
3823				setDefaultIdColor(cmMap_defaultIdColorPrev);
3824				var idColorFromOverlay=(cmMap_overlaysInMap[typeOfOverlay][idOverlay].styleId=='')?cmMap_defaultIdColor:cmMap_overlaysInMap[typeOfOverlay][idOverlay].styleId;
3825				cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setOptions({
3826					strokeColor: cmMap_overlayColors[idColorFromOverlay].strokeC,
3827					strokeOpacity: cmMap_overlayColors[idColorFromOverlay].strokeO,
3828					strokeWeight: cmMap_overlayColors[idColorFromOverlay].strokeW
3829				});
3830			break;
3831			case 'polygon': case 'rectangule': case 'circle':
3832				setDefaultIdColor(cmMap_defaultIdColorPrev);
3833				var idColorFromOverlay=(cmMap_overlaysInMap[typeOfOverlay][idOverlay].styleId=='')?cmMap_defaultIdColor:cmMap_overlaysInMap[typeOfOverlay][idOverlay].styleId;
3834				cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setOptions({
3835					strokeColor: cmMap_overlayColors[idColorFromOverlay].strokeC,
3836					strokeOpacity: cmMap_overlayColors[idColorFromOverlay].strokeO,
3837					strokeWeight: cmMap_overlayColors[idColorFromOverlay].strokeW,
3838					fillColor: cmMap_overlayColors[idColorFromOverlay].fillC,
3839					fillOpacity: cmMap_overlayColors[idColorFromOverlay].fillO
3840				});
3841			break;
3842			case 'markerNotInRoute':
3843				setDefaultIdImgMarker(cmMap_defaultIdImgMarkerPrev);
3844				var idImgFromMarker=(cmMap_overlaysInMap[typeOfOverlay][idOverlay].styleId=='')?cmMap_defaultIdImgMarker:cmMap_overlaysInMap[typeOfOverlay][idOverlay].styleId;
3845				cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setIcon(cmMap_markerImages[idImgFromMarker].icon);
3846				cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setShadow(cmMap_markerImages[idImgFromMarker].shadow);
3847			break;
3848			default:
3849		}
3850		cmMap_oldInfoWindow.close();
3851		//no hay ventana que cerrar, lo ponemos a null
3852		cmMap_oldInfoWindow=null;
3853	}
3854
3855    /**
3856     * Función que elimina una ruta del mapa
3857     * @memberOf MapsApi
3858     */
3859	var cmMap_deleteRouteInMap=function(){
3860		
3861		cmMap_closeOldWindow();
3862		//eliminas marcadores de la ruta y la linea (necesaria para hacer click en la ruta)
3863		cmMap_deleteOverlaysInMap('markerInRoute');
3864		cmMap_infoWindowInMap['markerInRoute']=[];
3865		cmMap_deleteOverlaysInMap('route');
3866		cmMap_infoWindowInMap['route']=[];
3867		
3868		cmMap_changeRouteByDrag=false;
3869		if(cmMap_markersRouteLatLng.length==(cmMap_MaxWaypoints+2)){
3870			//lanzamos evento de que el maximo punto de la ruta, ya no ha sido alcanzado
3871			googleMapObject.cmMap_container.trigger('maxWaypointNotReach');
3872		}
3873		if(cmMap_markersRouteLatLng.length>1){
3874			//eliminamos la ruta
3875			cmMap_directionsDisplay.setMap(null);
3876		}
3877		
3878		cmMap_markersRouteLatLng=[];
3879		if(cmMap_initialMarkerRoute){
3880			cmMap_initialMarkerRoute.setMap(null);
3881			cmMap_initialMarkerRoute='';
3882		}
3883	}
3884
3885    /**
3886     * Función que elimina un marcador
3887     * @param {string} typeOfOverlay - Tipo de overlay
3888     * @param {string} idOverlay - Id
3889     * @memberOf MapsApi
3890     */
3891	var cmMap_deleteAOverlayInMap=function(typeOfOverlay,idOverlay){
3892		cmMap_closeOldWindow();
3893		cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setMap(null);
3894		cmMap_overlaysInMap[typeOfOverlay][idOverlay].visible=false;
3895		//si es el marcador de una ruta, la volvemos a calcular
3896		if(typeOfOverlay=='markerInRoute'){
3897			//si es el ultimo elemento de la ruta, limpiamos la informacion
3898			if(cmMap_markersRouteLatLng.length==1){
3899				cmMap_deleteRouteInMap();
3900			}else{
3901				//si antes de eliminar tenia alcanzado el numero maximo de puntos, al leiminar uno, lanxamos el evento de que no se ha alcanzado el numero maximo
3902				if(cmMap_markersRouteLatLng.length==(cmMap_MaxWaypoints+2)){
3903					//lanzamos evento de que el maximo punto de la ruta, ya no ha sido alcanzado
3904					googleMapObject.cmMap_container.trigger('maxWaypointNotReach');
3905				}
3906				//eliminamos las coordenadas y detalles de informacion de ese marcador
3907				cmMap_markersRouteLatLng=cmMap_deleteElementFromArray(cmMap_markersRouteLatLng,idOverlay);
3908				cmMap_infoWindowInMap[typeOfOverlay]=cmMap_deleteElementFromArray(cmMap_infoWindowInMap[typeOfOverlay],idOverlay);
3909				if(cmMap_markersRouteLatLng.length>1){
3910					//si una vez eliminado, queda mas de un marcador, hacemos la ruta
3911					//si hemos eliminado el primer elemento, indicamos que el siguiente es el primer elemento ahora
3912					if(idOverlay==0){
3913						cmMap_initialMarkerRoute=cmMap_overlaysInMap[typeOfOverlay][1].overlay;
3914					}
3915					cmMap_createNewRoute(false,false,false,true,{},idOverlay);
3916				}else{
3917					//si una vez eliminado, solo queda un marcador, no se debe crear ruta, solo eliminarla
3918					cmMap_deleteOverlaysInMap('markerInRoute');
3919					cmMap_initialMarkerRoute=cmMap_createMarkerAndInfowin(cmMap_markerOptionsInRoute,cmMap_markersRouteLatLng[0],'markerInRoute',cmMap_createInfowinMarkerRoute,true,true,false,{});
3920					//indicamos que no estamos cambiando la ruta por hacer drag sobre ella
3921					cmMap_changeRouteByDrag=false;
3922					cmMap_directionsDisplay.setMap(null);
3923				}
3924			}
3925		}
3926		
3927		//si estamos en modo edicion tipo localizacion, lanzamos el  evento de que se puede poner un marcador en el mapa
3928		if(googleMapObject.cmMap_editableMode && googleMapObject.cmMap_typeParam=='location'){
3929			googleMapObject.cmMap_container.trigger('maxPointNoReach');
3930		}
3931	}
3932
3933    /**
3934     * Función para que puedan seleccionar un color las overlays que no son marcador
3935     * @param {string} typeOfOverlay - Tipo de overlay
3936     * @param {string} idOverlay - Id
3937     * @memberOf MapsApi
3938     */
3939	var cmMap_colorSelector=function(typeOfOverlay,idOverlay){
3940		var infoWindowOverlay=$('div.infoWindowOverlay');
3941		var infoWindowStyleLink=$("div.infoWindowStyleLink", infoWindowOverlay);
3942		var infoWindowStyleInfo=$("div.infoWindowStyleInfo", infoWindowOverlay);
3943		var infoWindowContent=$("div.infoWindowContent", infoWindowOverlay);
3944
3945		infoWindowStyleLink.addClass("infoWindowStyleLinkSelector");
3946		infoWindowStyleLink.click(function(){
3947
3948			var selectedColor = $("#styleId",infoWindowOverlay).val();
3949			if(selectedColor == '') selectedColor = cmMap_defaultIdColor;
3950			infoWindowStyleInfo.html(googleMapObject.cmMap_getOverlayColors(selectedColor));
3951
3952			infoWindowOverlay.parent().css({overflow:'hidden'});
3953
3954			$("div.colorOverlay",infoWindowOverlay).each(function(){
3955				$(this).click(function(){
3956					var idColor = $(this).attr('id');
3957					cmMap_defaultIdColorPrev = cmMap_defaultIdColor;
3958					setDefaultIdColor(idColor);
3959
3960					$("#styleId",infoWindowOverlay).val(idColor);
3961					$("div.colorOverlayToShow",infoWindowStyleLink).css({'background-color':cmMap_overlayColors[idColor].strokeC});
3962					infoWindowStyleInfo.css({display:'none'});
3963					infoWindowContent.css({display:'block'});
3964					if(typeOfOverlay == 'polyline') {
3965						cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setOptions({
3966							strokeColor: cmMap_overlayColors[idColor].strokeC,
3967							strokeOpacity: cmMap_overlayColors[idColor].strokeO,
3968							strokeWeight: cmMap_overlayColors[idColor].strokeW
3969						});
3970					}
3971					else {
3972						cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setOptions({
3973							strokeColor: cmMap_overlayColors[idColor].strokeC,
3974							strokeOpacity: cmMap_overlayColors[idColor].strokeO,
3975							strokeWeight: cmMap_overlayColors[idColor].strokeW,
3976							fillColor: cmMap_overlayColors[idColor].fillC,
3977							fillOpacity: cmMap_overlayColors[idColor].fillO
3978						});
3979					}
3980				});
3981			});
3982			infoWindowContent.css({display:'none'});
3983			infoWindowStyleInfo.css({display:'block'});
3984		});
3985	}
3986
3987    /**
3988     * Función para que poner un id color por defecto, con los cambios que eso conlleva
3989     * @param {string} _idColor - Color
3990     * @memberOf MapsApi
3991     */
3992	var setDefaultIdColor=function(_idColor){
3993		cmMap_defaultIdColor = _idColor;
3994		//se modifican los colores, anchos por defecto para el siguiente overlay que se dibuje
3995		googleMapObject.cmMap_defaultStyleOverlay={
3996			"strokeColor" : cmMap_overlayColors[cmMap_defaultIdColor].strokeC,
3997			"strokeOpacity" : cmMap_overlayColors[cmMap_defaultIdColor].strokeO,
3998			"strokeWeight" :cmMap_overlayColors[cmMap_defaultIdColor].strokeW,
3999			"fillColor" : cmMap_overlayColors[cmMap_defaultIdColor].fillC,
4000			"fillOpacity":cmMap_overlayColors[cmMap_defaultIdColor].fillO
4001		};
4002		//se indica al drawingmanger que por defecto muestre los overlays de otro color, anchura...
4003		cmMap_drawingManager.setOptions({
4004			polylineOptions:{editable:googleMapObject.cmMap_editableMode,strokeColor:googleMapObject.cmMap_defaultStyleOverlay['strokeColor'],strokeOpacity:googleMapObject.cmMap_defaultStyleOverlay['strokeOpacity'],strokeWeight:googleMapObject.cmMap_defaultStyleOverlay['strokeWeight']},
4005			polygonOptions:{editable:googleMapObject.cmMap_editableMode,strokeColor:googleMapObject.cmMap_defaultStyleOverlay['strokeColor'],strokeOpacity:googleMapObject.cmMap_defaultStyleOverlay['strokeOpacity'],strokeWeight:googleMapObject.cmMap_defaultStyleOverlay['strokeWeight'],fillColor:googleMapObject.cmMap_defaultStyleOverlay['fillColor'],fillOpacity:googleMapObject.cmMap_defaultStyleOverlay['fillOpacity']}
4006		});
4007	}
4008
4009    /**
4010     * Función para que puedan seleccionar un imgMarker los marcadores
4011     * @param {string} typeOfOverlay - Tipo de overlay
4012     * @param {string} idOverlay - Id
4013     * @memberOf MapsApi
4014     */
4015	var cmMap_imgSelector=function(typeOfOverlay,idOverlay){
4016		var infoWindowOverlay=$('div.infoWindowOverlay');
4017		var infoWindowStyleLink=$("div.infoWindowStyleLink", infoWindowOverlay);
4018		var infoWindowStyleInfo=$("div.infoWindowStyleInfo", infoWindowOverlay);
4019		var infoWindowContent=$("div.infoWindowContent", infoWindowOverlay);
4020
4021		infoWindowStyleLink.addClass("infoWindowStyleLinkSelector");
4022		infoWindowStyleLink.click(function(){
4023
4024			var selectedMarker = $("#styleId",infoWindowOverlay).val();
4025			if(selectedMarker == '') selectedMarker = cmMap_defaultIdImgMarker;
4026			infoWindowStyleInfo.html(googleMapObject.cmMap_getMarkerImages(selectedMarker));
4027
4028			infoWindowOverlay.parent().css({overflow:'hidden'});
4029
4030			$("img.image",infoWindowOverlay).each(function(){
4031				$(this).click(function(){
4032					var idImg = $(this).attr('id');
4033					cmMap_defaultIdImgMarkerPrev=cmMap_defaultIdImgMarker;
4034					setDefaultIdImgMarker(idImg);
4035					
4036					var objImg = $("img",infoWindowStyleLink);
4037					$("#styleId",infoWindowOverlay).val(idImg);
4038					objImg.attr('src',cmMap_markerImages[idImg].markerIcon);
4039					objImg.attr('title',cmMap_markerImages[idImg].name);
4040					if(cmMap_markerImages[idImg].icon["size"]) {
4041						objImg.attr("height",cmMap_markerImages[idImg].icon["size"].height);
4042						objImg.attr("width",cmMap_markerImages[idImg].icon["size"].width);
4043						if(cmMap_markerImages[idImg].icon["size"].height<40) {
4044							objImg.css("margin-top",parseInt((40-cmMap_markerImages[idImg].icon["size"].height)/2,10)+'px');
4045						}
4046					}
4047					infoWindowStyleInfo.css({display:'none'});
4048					infoWindowContent.css({display:'block'});
4049					cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setIcon(cmMap_markerImages[idImg].icon);
4050					cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setShadow(cmMap_markerImages[idImg].shadow);
4051				});
4052			});
4053			infoWindowContent.css({display:'none'});
4054			infoWindowStyleInfo.css({display:'block'});
4055		});
4056	}
4057
4058    /**
4059     * Función para que poner un id color por defecto, con los cambios que eso conlleva
4060     * @param {string} _idImg - Id
4061     * @memberOf MapsApi
4062     */
4063	var setDefaultIdImgMarker=function(_idImg){
4064		cmMap_defaultIdImgMarker = _idImg;
4065		//se modifican el marcador por defecto para el siguiente que dibuje
4066		cmMap_markerOptions={icon: cmMap_markerImages[cmMap_defaultIdImgMarker].icon,shadow:cmMap_markerImages[cmMap_defaultIdImgMarker].shadow,draggable:googleMapObject.cmMap_editableMode};
4067		//se indica al drawingmanger que por defecto muestre los overlays de otro color, anchura...
4068		cmMap_drawingManager.setOptions({
4069			markerOptions: cmMap_markerOptions
4070		});
4071	}
4072
4073    /**
4074     * Función que guarda la información que hay en el formulario
4075     * @memberOf MapsApi
4076     */
4077	var cmMap_saveFromFormAndCloseInfowin=function(){
4078		cmMap_saveFromFormInfowin($("#infoWindowForm"));
4079		cmMap_oldInfoWindow.close();
4080		//no hay ventana que cerrar, lo ponemos a null
4081		cmMap_oldInfoWindow=null;
4082	}
4083
4084    /**
4085     *
4086     * @param form
4087     * @memberOf MapsApi
4088     */
4089	var cmMap_saveFromFormInfowin=function(form){
4090		var typeOfOverlay=$('#typeOfOverlay',form).val();
4091		var idOverlay=$('#id_overlay',form).val();
4092		
4093		//si es igual la marker in route no hay nada que guardar
4094		if(typeOfOverlay!='markerInroute'){
4095			cmMap_saveInfo(typeOfOverlay,idOverlay,$('#name',form).val(),$('#description',form).val(),$('#linkText_url',form).val(),$('#link_idContent',form).val(),$('#link_alias',form).val(),$('#linkText_content',form).val(),$('#styleId',form).val());
4096		}
4097	}
4098
4099    /**
4100     * Función que guarda la información de un mapa
4101     * @param {string} typeOfOverlay - Tipo de overlay
4102     * @param {string} idOverlay - Id
4103     * @param {string} name - Nombre
4104     * @param {string} description - Descripción
4105     * @param {string} url - Url
4106     * @param {string} idContent - Id Contenido
4107     * @param {string} alias - Alias
4108     * @param {string} content - Contenido
4109     * @param {string} style - Style
4110     * @memberOf MapsApi
4111     */
4112	var cmMap_saveInfo=function(typeOfOverlay,idOverlay,name,description,url,idContent,alias,content,style){
4113		cmMap_overlaysInMap[typeOfOverlay][idOverlay].name = name;
4114		if(typeOfOverlay=='markerNotInRoute'){
4115			cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setTitle(name);
4116		}
4117		cmMap_overlaysInMap[typeOfOverlay][idOverlay].description =  description;
4118		if($("#linkType_url").is(":checked")) {
4119			cmMap_overlaysInMap[typeOfOverlay][idOverlay].url = (url)?url:'';
4120			cmMap_overlaysInMap[typeOfOverlay][idOverlay].idContent = '';
4121			cmMap_overlaysInMap[typeOfOverlay][idOverlay].alias = '';
4122			cmMap_overlaysInMap[typeOfOverlay][idOverlay].content = '';
4123		}
4124		else {
4125			cmMap_overlaysInMap[typeOfOverlay][idOverlay].url = '';
4126			cmMap_overlaysInMap[typeOfOverlay][idOverlay].idContent = idContent;
4127			cmMap_overlaysInMap[typeOfOverlay][idOverlay].alias = alias;
4128			cmMap_overlaysInMap[typeOfOverlay][idOverlay].content = content;
4129		}
4130		cmMap_overlaysInMap[typeOfOverlay][idOverlay].styleId = style;
4131		cmMap_infoWindowInMap[typeOfOverlay][idOverlay].infoWindow.setContent(cmMap_createContentInfowin(typeOfOverlay,idOverlay));
4132	}
4133
4134    /**
4135     * Función para generar un kml pero por partes. Se utiliza en el modo editable tipo localizacion
4136     * @memberOf MapsApi
4137     */
4138	var cmMap_locationGeneratorType=function(){
4139		//es para marcadores que no esten en una ruta, que son los unicos que hay en modo editable tipo localizacion
4140		kmlStyle='';
4141		kmlStyleUrl='';
4142		kmlPoint='';
4143		kmlCoordLng='';
4144		kmlCoordLat='';
4145		// Descomentar lo siguiente para incluir el es
4145tilo del marker en el documento kml
4146		//kmlStyle=cmMap_createStyleForKml('markerNotInRoute',kmlStyle);
4147		cmMap_createMarkerForLocation();
4148		
4149		//esto en vez de mostrarlo se tendria que guardar
4150		/*
4151		$("div.output .style").val(kmlStyle);
4152		$("div.output .styleUrl").val(kmlStyleUrl);
4153		$("div.output .point").val(kmlPoint);
4154		$("div.output .coordLng").val(kmlCoordLng);
4155		$("div.output .coordLat").val(kmlCoordLat);
4156		*/
4157	}
4158
4159    /**
4160     * Función para generar un kml de los elementos del mapa (genera el kml)
4161     * @returns {string}
4162     * @memberOf MapsApi
4163     */
4164	var cmMap_kmlGeneratorType=function(){
4165		var kmlToSave='';
4166
4167		// Descomentar lo siguiente para incluir los estilos en el documento kml
4168		/*for (idTypeOfOverlay in cmMap_overlaysInMap){
4169			if(idTypeOfOverlay!='route'){
4170				if(idTypeOfOverlay!='markerInRoute'){
4171					kmlToSave=cmMap_createStyleForKml(idTypeOfOverlay,kmlToSave);
4172				}else{
4173					if(cmMap_markersRouteLatLng.length>1)kmlToSave=cmMap_createStyleRouteForKml(idTypeOfOverlay,kmlToSave);
4174				}
4175			}
4176		}*/
4177		
4178		// Si hemos definido un nivel de zoom y centrado personalizados lo guardamos en el KML
4179		if(($("#cmMap_customZoomLevel").length > 0 && $("#cmMap_customZoomLevel").is(":checked")) || googleMapObject.cmMap_mapTypeId!=cmMap_mapTypeId || googleMapObject.cmMap_icon!=null) {
4180			kmlToSave+='<ExtendedData>\n';
4181			// El icono asociado al elemento 
4182			if(googleMapObject.cmMap_icon != null) {
4183				kmlToSave+='\t<Data name="styleUrl">\n';
4184				kmlToSave+='\t\t<value>'+googleMapObject.cmMap_icon+'</value>\n';
4185				kmlToSave+='\t</Data>\n';
4186			}
4187
4188			if($("#cmMap_customZoomLevel").length > 0 && $("#cmMap_customZoomLevel").is(":checked")) {
4189				kmlToSave+='\t<Data name="zoomLevel">\n';
4190				kmlToSave+='\t\t<value>'+$("#cmMap_zoomLevelSelect").val()+'</value>\n';
4191				kmlToSave+='\t</Data>\n';
4192				kmlToSave+='\t<Data name="centerCoords">\n';
4193				kmlToSave+='\t\t<value>'+$("#cmMap_zoomCenter").text()+'</value>\n';
4194				kmlToSave+='\t</Data>\n';
4195			}		
4196			if(googleMapObject.cmMap_mapTypeId!=cmMap_mapTypeId){
4197				kmlToSave+='\t<Data name="mapTypeId">\n';
4198				kmlToSave+='\t\t<value>'+googleMapObject.cmMap_mapTypeId+'</value>\n';
4199				kmlToSave+='\t</Data>\n';
4200			}
4201			kmlToSave+='</ExtendedData>\n';
4202		}
4203
4204		for (idTypeOfOverlay in cmMap_overlaysInMap){
4205			if(idTypeOfOverlay!='route'){
4206				if(idTypeOfOverlay!='markerInRoute'){
4207					kmlToSave = cmMap_createOverlayForKml(idTypeOfOverlay,kmlToSave);
4208				}else{
4209					if(cmMap_markersRouteLatLng.length>1)
4210						kmlToSave = cmMap_createRouteForKml(idTypeOfOverlay,kmlToSave);
4211				}
4212			}
4213		}
4214		return kmlToSave;
4215	}
4216
4217    /**
4218     * Función para crear estilos para el kml
4219     * @param {string} typeOfOverlay - Tipo de overlay
4220     * @param kmlToSave - Kml a guardar
4221     * @returns {*}
4222     * @memberOf MapsApi
4223     */
4224	var cmMap_createStyleForKml=function(typeOfOverlay,kmlToSave){
4225		var arrayStyleCreate=new Array();
4226		for(var i=0;i<cmMap_overlaysInMap[typeOfOverlay].length;i++){
4227			if(cmMap_overlaysInMap[typeOfOverlay][i].visible){
4228				var styleCreateAlready=false;
4229				if(cmMap_overlaysInMap[typeOfOverlay][i].styleId==''){
4230					if(typeOfOverlay=='markerNotInRoute')cmMap_overlaysInMap[typeOfOverlay][i].styleId=cmMap_defaultIdImgMarker;
4231					if(typeOfOverlay!='markerInRoute' && typeOfOverlay!='markerNotInRoute')cmMap_overlaysInMap[typeOfOverlay][i].styleId=cmMap_defaultIdColor;
4232				}
4233				var styleIdToSave=cmMap_overlaysInMap[typeOfOverlay][i].styleId;
4234				for(var j=0;j<arrayStyleCreate.length;j++){
4235					if((typeOfOverlay=='markerNotInRoute' && arrayStyleCreate[j]==styleIdToSave) || (typeOfOverlay=='markerInRoute' && arrayStyleCreate[j]==markerInRoute) ||((typeOfOverlay=='polygon' || typeOfOverlay=='rectangule' || typeOfOverlay=='circle') && arrayStyleCreate[j]=="polygon_"+styleIdToSave)||(typeOfOverlay=='polyline' && arrayStyleCreate[j]=="polyline_"+styleIdToSave)){
4236						styleCreateAlready=true;
4237					}
4238				}
4239				//si no se ha creado lo creamos
4240				if(!styleCreateAlready && typeOfOverlay=='markerNotInRoute'){
4241					arrayStyleCreate.push(styleIdToSave);
4242					kmlToSave+='<Style id="'+styleIdToSave+'">\n';
4243					kmlToSave+='\t<IconStyle>\n';
4244					kmlToSave+='\t\t<Icon>\n';
4245					kmlToSave+='\t\t\t<href>';
4246					kmlToSave+=cmMap_rootWeb+cmMap_markerImages[styleIdToSave].markerIcon;
4247					kmlToSave+='</href>\n';
4248					kmlToSave+='\t\t</Icon>\n';
4249					kmlToSave+='\t</IconStyle>\n';
4250					kmlToSave+='</Style>\n';
4251				}
4252				
4253				//si no se ha creado lo creamos
4254				if(!styleCreateAlready && typeOfOverlay=='markerInRoute'){
4255					arrayStyleCreate.push(markerInRoute);
4256					kmlToSave+='<Style id="markerInRoute">\n';
4257					kmlToSave+='\t<LineStyle>\n';
4258					kmlToSave+='\t\t<color>';
4259					kmlToSave+='73FF0000';
4260					kmlToSave+='</color>\n';
4261					kmlToSave+='\t\t<width>5</width>\n';
4262					kmlToSave+='\t</LineStyle>\n';
4263					kmlToSave+='</Style>\n';
4264				}
4265				//si no se ha creado lo creamos
4266				if(!styleCreateAlready && (typeOfOverlay=='polygon' || typeOfOverlay=='rectangule' || typeOfOverlay=='circle')){
4267					arrayStyleCreate.push("polygon_"+styleIdToSave);
4268					kmlToSave+='<Style id="polygon_'+styleIdToSave+'">\n';
4269					kmlToSave+='\t<LineStyle>\n';
4270					kmlToSave+='\t\t<color>';
4271					kmlToSave+='73'+cmMap_overlayColors[styleIdToSave].strokeC.substring(1);
4272					kmlToSave+='</color>\n';
4273					kmlToSave+='\t\t<width>3</width>\n';
4274					kmlToSave+='\t</LineStyle>\n';
4275					kmlToSave+='\t<PolyStyle>\n';
4276					kmlToSave+='\t\t<color>';
4277					kmlToSave+='73'+cmMap_overlayColors[styleIdToSave].strokeC.substring(1);
4278					kmlToSave+='</color>\n';
4279					kmlToSave+='\t\t<fill>1</fill>\n';
4280					kmlToSave+='\t\t<outline>1</outline>\n';
4281					kmlToSave+='\t</PolyStyle>\n';
4282					kmlToSave+='</Style>\n';
4283				}
4284				
4285				//si no se ha creado lo creamos
4286				if(!styleCreateAlready && typeOfOverlay=='polyline'){
4287					arrayStyleCreate.push("polyline_"+styleIdToSave);
4288					kmlToSave+='<Style id="polyline_'+styleIdToSave+'">\n';
4289					kmlToSave+='\t<LineStyle>\n';
4290					kmlToSave+='\t\t<color>';
4291					kmlToSave+='73'+cmMap_overlayColors[styleIdToSave].strokeC.substring(1);
4292					kmlToSave+='</color>\n';
4293					kmlToSave+='\t\t<width>5</width>\n';
4294					kmlToSave+='\t</LineStyle>\n';
4295					kmlToSave+='</Style>\n';
4296				}
4297			}
4298		}
4299		return kmlToSave;
4300	}
4301
4302    /**
4303     * Función para guarda un overlay en el kml
4304     * @param {string} typeOfOverlay - Tipo de overlay
4305     * @param kmlToSave - Kml a guardar
4306     * @returns {*}
4307     * @memberOf MapsApi
4308     */
4309	var cmMap_createOverlayForKml=function(typeOfOverlay,kmlToSave){
4310		for(var i=0;i<cmMap_overlaysInMap[typeOfOverlay].length;i++){
4311			var currentOverlay = cmMap_overlaysInMap[typeOfOverlay][i];
4312			if(currentOverlay.visible){
4313				kmlToSave+='<Placemark>\n';
4314				kmlToSave+='\t<name>';
4315				kmlToSave+=currentOverlay.name;
4316				kmlToSave+='</name>\n';
4317				kmlToSave+='\t<description>';
4318				kmlToSave+=currentOverlay.description;
4319				kmlToSave+='</description>\n';
4320				kmlToSave+='\t<Link>';
4321				if(currentOverlay.url && currentOverlay.url != '') {
4322					kmlToSave+=currentOverlay.url;
4323				}
4324				else if(currentOverlay.idContent != '' && currentOverlay.alias != '') {
4325					kmlToSave+='[INTERNAL_URL idContent="'+currentOverlay.idContent+'" alias="'+currentOverlay.alias+'" name="'+cmMap_encodeString(currentOverlay.content)+'"]';
4326				}
4327				kmlToSave+='</Link>\n';
4328				kmlToSave+='\t<styleUrl>';
4329				if(typeOfOverlay=='markerNotInRoute'){
4330					kmlToSave+='#'+currentOverlay.styleId;
4331				} else if(typeOfOverlay=='polyline'){
4332					kmlToSave+='#polyline_'+currentOverlay.styleId;
4333				} else if(typeOfOverlay=='polygon'){
4334					kmlToSave+='#polygon_'+currentOverlay.styleId;
4335				}
4336				kmlToSave+='</styleUrl>\n';
4337				if(typeOfOverlay=='markerNotInRoute'){
4338					kmlToSave+='\t<Point>\n';
4339					kmlToSave+='\t\t<coordinates>';
4340					kmlToSave+=currentOverlay.overlay.getPosition().lng()+","+currentOverlay.overlay.getPosition().lat()+",0";
4341					kmlToSave+='</coordinates>\n';
4342					kmlToSave+='\t</Point>\n';
4343				} else if(typeOfOverlay=='polyline'){
4344					kmlToSave+='\t<LineString>\n';
4345					kmlToSave+='\t\t<tessellate>1</tessellate>\n';
4346					kmlToSave+='\t\t<coordinates>\n';
4347					var path=currentOverlay.overlay.getPath();
4348					for(var j=0;j<path.getLength();j++){
4349						kmlToSave+='\t\t\t'+path.getAt(j).lng()+","+path.getAt(j).lat()+",0\n";
4350					}
4351					kmlToSave+='\t\t</coordinates>\n';
4352					kmlToSave+='\t</LineString>\n';
4353				} else if(typeOfOverlay=='polygon'){
4354					kmlToSave+='\t<Polygon>\n';
4355					kmlToSave+='\t\t<outerBoundaryIs>\n';
4356					kmlToSave+='\t\t\t<LinearRing>\n';
4357					kmlToSave+='\t\t\t\t<tessellate>1</tessellate>\n';
4358					kmlToSave+='\t\t\t\t<coordinates>\n';
4359					var path=currentOverlay.overlay.getPath();
4360					for(var j=0;j<path.getLength();j++){
4361						kmlToSave+='\t\t\t\t\t'+path.getAt(j).lng()+","+path.getAt(j).lat()+",0\n";
4362					}
4363					kmlToSave+='\t\t\t\t</coordinates>\n';
4364					kmlToSave+='\t\t\t</LinearRing>\n';
4365					kmlToSave+='\t\t</outerBoundaryIs>\n';
4366					kmlToSave+='\t</Polygon>\n';
4367				}
4368				kmlToSave+='</Placemark>\n';
4369			}
4370		}
4371		return kmlToSave;
4372	}
4373
4374    /**
4375     * Función para guardar el estilo de la ruta
4376     * @param {string} typeOfOverlay - Tipo de overlay
4377     * @param kmlToSave - Kml a guardar
4378     * @returns {string}
4379     * @memberOf MapsApi
4380     */
4381	var cmMap_createStyleRouteForKml=function(typeOfOverlay,kmlToSave){
4382		kmlToSave+='<Style id="markerInRoute">\n';
4383		kmlToSave+='\t<LineStyle>\n';
4384		kmlToSave+='\t\t<color>';
4385		kmlToSave+='73FF0000';
4386		kmlToSave+='</color>\n';
4387		kmlToSave+='\t\t<width>5</width>\n';
4388		kmlToSave+='\t</LineStyle>\n';
4389		kmlToSave+='</Style>\n';
4390		return kmlToSave;
4391	}
4392
4393    /**
4394     * Función para guardar una ruta desde el kml
4395     * @param {string} typeOfOverlay - Tipo de overlay
4396     * @param kmlToSave - Kml a guardar
4397     * @returns {string}
4398     * @memberOf MapsApi
4399     */
4400	var cmMap_createRouteForKml=function(typeOfOverlay,kmlToSave){
4401		kmlToSave+='<Placemark>\n';
4402		kmlToSave+='\t<name>';
4403		kmlToSave+=cmMap_overlaysInMap['route'][0].name;
4404		kmlToSave+='</name>\n';
4405		kmlToSave+='\t<description>';
4406		kmlToSave+=cmMap_overlaysInMap['route'][0].description;
4407		kmlToSave+='</description>\n';
4408		kmlToSave+='\t<Link>';
4409		if(cmMap_overlaysInMap['route'][0].url && cmMap_overlaysInMap['route'][0].url != '') {
4410			kmlToSave+=cmMap_overlaysInMap['route'][0].url;
4411		}
4412		else if(cmMap_overlaysInMap['route'][0].idContent != '' && cmMap_overlaysInMap['route'][0].alias != '') {
4413			kmlToSave+='[INTERNAL_URL idContent="'+cmMap_overlaysInMap['route'][0].idContent+'" alias="'+cmMap_overlaysInMap['route'][0].alias+'" name="'+cmMap_encodeString(cmMap_overlaysInMap['route'][0].content)+'"]';
4414		}
4415		kmlToSave+='</Link>\n';
4416		kmlToSave+='\t<styleUrl>';
4417		kmlToSave+='#markerInRoute';
4418		kmlToSave+='</styleUrl>\n';
4419		kmlToSave+='\t<ExtendedData>\n';
4420		kmlToSave+='\t\t<Data name="_SnapToRoads">\n';
4421		kmlToSave+='\t\t\t<value>true</value>\n';
4422		kmlToSave+='\t\t</Data>\n';
4423		kmlToSave+='\t</ExtendedData>\n';
4424		kmlToSave+='\t<LineString>\n';
4425		kmlToSave+='\t\t<tessellate>1</tessellate>\n';
4426		kmlToSave+='\t\t<coordinates>\n';
4427		for(var i=0;i<cmMap_overlaysInMap[typeOfOverlay].length;i++){
4428			if(cmMap_overlaysInMap[typeOfOverlay][i].visible){
4429				kmlToSave+='\t\t\t'+cmMap_overlaysInMap[typeOfOverlay][i].overlay.getPosition().lng()+","+cmMap_overlaysInMap[typeOfOverlay][i].overlay.getPosition().lat()+",0\n";
4430			}
4431		}
4432		kmlToSave+='\t\t</coordinates>\n';
4433		kmlToSave+='\t</LineString>\n';
4434		kmlToSave+='</Placemark>\n';
4435		return kmlToSave;
4436	}
4437
4438    /**
4439     * Función para guarda un marcador en distintas variables (modo editable tipo localizacion)
4440     * @memberOf MapsApi
4441     */
4442	var cmMap_createMarkerForLocation=function(){
4443		for(var i=0;i<cmMap_overlaysInMap['markerNotInRoute'].length;i++){
4444			if(cmMap_overlaysInMap['markerNotInRoute'][i].visible){
4445				kmlStyleUrl='<styleUrl>';
4446				kmlStyleUrl+='#'+cmMap_overlaysInMap['markerNotInRoute'][i].styleId;
4447				kmlStyleUrl+='</styleUrl>';
4448	
4449				kmlPoint='<Point>\n';
4450				kmlPoint+='\t<coordinates>';
4451				kmlPoint+=cmMap_overlaysInMap['markerNotInRoute'][i].overlay.getPosition().lng()+","+cmMap_overlaysInMap['markerNotInRoute'][i].overlay.getPosition().lat()+",0";
4452				kmlPoint+='</coordinates>\n';
4453				kmlPoint+='</Point>';
4454				
4455				kmlCoordLat=cmMap_overlaysInMap['markerNotInRoute'][i].overlay.getPosition().lat();
4456				kmlCoordLng=cmMap_overlaysInMap['markerNotInRoute'][i].overlay.getPosition().lng();
4457			}
4458		}
4459	}
4460
4461    // ESTA FUNCION NO SE USA PERO PODRIA SER UTIL EN EL FUTURO
4462    /**
4463     * Función que carga las imagenes para los marker permitidos en el proyecto
4464     * @param fnDone
4465     * @param datosMapa
4466     * @memberOf MapsApi
4467     */
4468	googleMapObject.cmMap_loadIconMarkerList=function(fnDone,datosMapa){
4469		$.ajax({
4470			url: cmMap_rootWeb+"/cm/"+cmMap_currentWeb+"/"+((wizardMode || $("body").hasClass("cmWizardEditMode"))?'wizard/':'')+"tkGMapsIcons",
4471			type: 'POST',
4472			data: "locale="+cmMap_lang,
4473			dataType: $.browser.msie ? 'text' : 'xml'
4474		}).done(function(xml){
4475			if(typeof(xml) == "string") xml = $.parseXML(xml);
4476			//googleMapObject.cmMap_processMessages(cmMap_messages);
4477			googleMapObject.cmMap_processIconMarkerList(xml);
4478			if(typeof(fnDone) == 'function') { fnDone(datosMapa); }
4479		});
4480	}
4481
4482    /**
4483     * Función que procesa las imagenes para los marker permitidos en el proyecto
4484     * @param xml
4485     * @memberOf MapsApi
4486     */
4487	googleMapObject.cmMap_processIconMarkerList=function(xml){
4488
4489		//valores marker por defecto
4490		var cmMap_defaultSrcImgMarker = googleMapObject.cmMap_defaultImageMarker.url;
4491		var cmMap_defaultNameMarker = resolveMessageinGmaps('{places}');
4492
4493		cmMap_markerImages[cmMap_defaultIdImgMarker] = new Array();
4494		cmMap_markerImages[cmMap_defaultIdImgMarker].icon = googleMapObject.cmMap_defaultImageMarker;
4495		cmMap_markerImages[cmMap_defaultIdImgMarker].shadow = googleMapObject.cmMap_defaultShadowMarker;
4496		cmMap_markerImages[cmMap_defaultIdImgMarker].idImg = cmMap_defaultIdImgMarker;
4497		cmMap_markerImages[cmMap_defaultIdImgMarker].markerIcon = cmMap_defaultSrcImgMarker;
4498		cmMap_markerImages[cmMap_defaultIdImgMarker].name = cmMap_defaultNameMarker;
4499		cmMap_markerImages[cmMap_defaultIdImgMarker].desc = "";
4500		cmMap_markerImages[cmMap_defaultIdImgMarker].parentIcon = "";
4501		cmMap_markerImages[cmMap_defaultIdImgMarker].noClusterAtZoom = "";
4502		cmMap_markerImages[cmMap_defaultIdImgMarker].baseClassName = "";
4503		cmMap_markerImages[cmMap_defaultIdImgMarker].thumbnail = "";
4504
4505		cmMap_markerImagesLength++;
4506		
4507		if($("marker", xml).length > 0) {
4508			$("marker", xml).each(function(i) {
4509				var idImg = $(this).attr('idIcon');
4510				var parentIcon = $(this).attr('parentIcon');
4511				var noClusterAtZoom = $(this).attr('noClusterAtZoom');
4512				var baseClassName = $(this).attr('baseClassName');
4513				var thumbnail = $(this).attr('thumbnail');
4514
4515				var markerIcon = ($(this).attr('markerIcon') && $(this).attr('markerIcon') != "") ? $(this).attr('markerIcon') : cmMap_defaultImageMarker.url;
4516				var markerWidth = ($(this).attr('markerWidth') && $(this).attr('markerWidth') != "") ? parseInt($(this).attr('markerWidth'),10) : cmMap_defaultImageMarker.size.width;
4517				var markerHeight = ($(this).attr('markerHeight') && $(this).attr('markerHeight') != "") ? parseInt($(this).attr('markerHeight'),10) : cmMap_defaultImageMarker.size.height;
4518				var markerX = ($(this).attr('markerX') && $(this).attr('markerX') != "") ? parseInt($(this).attr('markerX'),10) : cmMap_defaultImageMarker.anchor.x;
4519				var markerY = ($(this).attr('markerY') && $(this).attr('markerY') != "") ? parseInt($(this).attr('markerY'),10) : cmMap_defaultImageMarker.anchor.y;
4520
4521				var clusterIcon = ($(this).attr('clusterIcon') && $(this).attr('clusterIcon') != "") ? $(this).attr('clusterIcon') : cmMap_defaultImageCluster.url;
4522				var clusterWidth = ($(this).attr('clusterWidth') && $(this).attr('clusterWidth') != "") ? parseInt($(this).attr('clusterWidth'),10) : cmMap_defaultImageCluster.size.width;
4523				var clusterHeight = ($(this).attr('clusterHeight') && $(this).attr('clusterHeight') != "") ? parseInt($(this).attr('clusterHeight'),10) : cmMap_defaultImageCluster.size.height;
4524				var clusterX = ($(this).attr('clusterX') && $(this).attr('clusterX') != "") ? parseInt($(this).attr('clusterX'),10) : cmMap_defaultImageCluster.anchor.x;
4525				var clusterY = ($(this).attr('clusterY') && $(this).attr('clusterY') != "") ? parseInt($(this).attr('clusterY'),10) : cmMap_defaultImageCluster.anchor.y;
4526
4527				var shadowIcon = ($(this).attr('shadowIcon') && $(this).attr('shadowIcon') != "") ? $(this).attr('shadowIcon') : cmMap_defaultShadowMarker.url;
4528				var shadowWidth = ($(this).attr('shadowWidth') && $(this).attr('shadowWidth') != "") ? parseInt($(this).attr('shadowWidth'),10) : cmMap_defaultShadowMarker.size.width;
4529				var shadowHeight = ($(this).attr('shadowHeight') && $(this).attr('shadowHeight') != "") ? parseInt($(this).attr('shadowHeight'),10) : cmMap_defaultShadowMarker.size.height;
4530				var shadowX = ($(this).attr('shadowX') && $(this).attr('shadowX') != "") ? parseInt($(this).attr('shadowX'),10) : cmMap_defaultShadowMarker.anchor.x;
4531				var shadowY = ($(this).attr('shadowY') && $(this).attr('shadowY') != "") ? parseInt($(this).attr('shadowY'),10) : cmMap_defaultShadowMarker.anchor.y;
4532
4533				var markerName = $("name", this).text();
4534				var markerDesc = $("description", this).text();
4535
4536				cmMap_markerImages['img_'+idImg] = new Array();
4537				cmMap_markerImages['img_'+idImg].icon = new google.maps.MarkerImage(
4538					markerIcon,
4539					new google.maps.Size(markerWidth, markerHeight),
4540					null,
4541					new google.maps.Point(markerX, markerY)
4542				);
4543				cmMap_markerImages['img_'+idImg].shadow = new google.maps.MarkerImage(
4544					shadowIcon,
4545					new google.maps.Size(shadowWidth, shadowHeight),
4546					null,
4547					new google.maps.Point(shadowX, shadowY)
4548				);
4549				cmMap_markerImages['img_'+idImg].cluster = new google.maps.MarkerImage(
4550					clusterIcon,
4551					new google.maps.Size(clusterWidth, clusterHeight),
4552					null,
4553					new google.maps.Point(clusterX, clusterY)
4554				);
4555				cmMap_markerImages['img_'+idImg].idImg = 'img_'+idImg;
4556				cmMap_markerImages['img_'+idImg].markerIcon = markerIcon;
4557				cmMap_markerImages['img_'+idImg].name = markerName;
4558				cmMap_markerImages['img_'+idImg].desc = markerDesc;
4559				cmMap_markerImages['img_'+idImg].parentIcon = parentIcon;
4560				cmMap_markerImages['img_'+idImg].noClusterAtZoom = noClusterAtZoom;
4561				cmMap_markerImages['img_'+idImg].baseClassName = baseClassName;
4562				cmMap_markerImages['img_'+idImg].thumbnail = thumbnail;
4563				cmMap_markerImagesLength++;
4564			});
4565		}
4566	}
4567
4568    /**
4569     * Función que devuelve las imagenes para los marker permitidos en el proyecto
4570     * @param idImg
4571     * @returns {string}
4572     * @memberOf MapsApi
4573     */
4574	googleMapObject.cmMap_getMarkerImages=function(idImg){
4575		var markerImages = '';
4576		for(var i in cmMap_markerImages) {
4577			markerImages += '<img id="'+cmMap_markerImages[i].idImg+'" class="image'+((idImg && idImg == cmMap_markerImages[i].idImg)?' selected':'')+'" src="'+cmMap_markerImages[i].markerIcon+'" title="'+cmMap_markerImages[i].name+'"/>\n';
4578		}
4579		return markerImages;
4580	}
4581
4582    /**
4583     * Función que guarda en un array los mensajes que se deben mostrar
4584     * @param xml
4585     * @memberOf MapsApi
4586     */
4587	googleMapObject.cmMap_processMessages=function(xml){
4588		if($("property", xml).length > 0) {
4589			$("property", xml).each(function(i) {
4590				var key=$(this).attr('key');
4591				cmMap_messages['{'+key+'}']=$(this).text();
4592			});
4593		}
4594	}
4595
4596
4597    // ESTA FUNCION NO SE USA PERO PODRIA SER UTIL EN EL FUTURO
4598    /**
4599     * Función que carga los colores permitidos en el proyecto para los overlays
4600     * @param datosMapa - Datos del mapa
4601     * @memberOf MapsApi
4602     */
4603	googleMapObject.cmMap_loadColorOverlayList=function(datosMapa){
4604		$.ajax({
4605			url: cmMap_rootWeb+"/cm/"+cmMap_currentWeb+"/"+((wizardMode || $("body").hasClass("cmWizardEditMode"))?'wizard/':'')+"tkGMapsColors",
4606			type: 'POST',
4607			data: "locale="+cmMap_lang,
4608			dataType: $.browser.msie ? 'text' : 'xml'
4609		}).done(function(xml){
4610			if(typeof(xml) == "string") xml = $.parseXML(xml);
4611			googleMapObject.cmMap_processColorOverlayList(xml);
4612			//CARGAS EL MAPA
4613			googleMapObject.cmMap_initialize(datosMapa);
4614		});
4615	}
4616
4617    /**
4618     * Función que carga los colores permitidos en el proyecto para los overlays
4619     * @param xml
4620     * @memberOf MapsApi
4621     */
4622	googleMapObject.cmMap_processColorOverlayList=function(xml){
4623		//valor por defecto
4624		var strokeC=googleMapObject.cmMap_defaultStyleOverlay['strokeColor'];
4625		var strokeO=googleMapObject.cmMap_defaultStyleOverlay['strokeOpacity'];
4626		var strokeW=googleMapObject.cmMap_defaultStyleOverlay['strokeWeight'];
4627		var fillC=googleMapObject.cmMap_defaultStyleOverlay['fillColor'];
4628		var fillO=googleMapObject.cmMap_defaultStyleOverlay['fillOpacity'];
4629		var cmMap_defaultNameColor = "Negro";
4630		cmMap_overlayColors[cmMap_defaultIdColor] = new Array();
4631		cmMap_overlayColors[cmMap_defaultIdColor].idColor = cmMap_defaultIdColor;
4632		cmMap_overlayColors[cmMap_defaultIdColor].strokeC = strokeC;
4633		cmMap_overlayColors[cmMap_defaultIdColor].strokeO = strokeO;
4634		cmMap_overlayColors[cmMap_defaultIdColor].strokeW = strokeW;
4635		cmMap_overlayColors[cmMap_defaultIdColor].fillC = fillC;
4636		cmMap_overlayColors[cmMap_defaultIdColor].fillO = fillO;
4637		cmMap_overlayColors[cmMap_defaultIdColor].name = cmMap_defaultNameColor;
4638		cmMap_overlayColors[cmMap_defaultIdColor].desc = "";
4639		cmMap_overlayColors[cmMap_defaultIdColor].parentIcon = "";
4640		cmMap_overlayColors[cmMap_defaultIdColor].noClusterAtZoom = "";
4641		cmMap_overlayColors[cmMap_defaultIdColor].baseClassName = "";
4642		cmMap_overlayColors[cmMap_defaultIdColor].thumbnail = "";
4643
4644		cmMap_overlayColorsLength++;
4645
4646		if($("color", xml).length > 0) {
4647			$("color", xml).each(function(i) {
4648
4649				var idColor = $(this).attr('idColor');
4650				var strokeC = ($(this).attr('strokeC') && $(this).attr('strokeC') != "") ? $(this).attr('strokeC') : strokeC;
4651				var strokeO = ($(this).attr('strokeO') && $(this).attr('strokeO') != "") ? $(this).attr('strokeO') : strokeO;
4652				var strokeW = ($(this).attr('strokeW') && $(this).attr('strokeW') != "") ? $(this).attr('strokeW') : strokeW;
4653				var fillC = ($(this).attr('fillC') && $(this).attr('fillC') != "") ? $(this).attr('fillC') : fillC;
4654				var fillO = ($(this).attr('fillO') && $(this).attr('fillO') != "") ? $(this).attr('fillO') : fillO;
4655
4656				var colorName = $("name", this).text();
4657				var colorDesc = $("description", this).text();
4658
4659				cmMap_overlayColors['color_'+idColor] = new Array();
4660				cmMap_overlayColors['color_'+idColor].idColor = 'color_'+idColor;
4661				cmMap_overlayColors['color_'+idColor].strokeC = strokeC;
4662				cmMap_overlayColors['color_'+idColor].strokeO = strokeO;
4663				cmMap_overlayColors['color_'+idColor].strokeW = strokeW;
4664				cmMap_overlayColors['color_'+idColor].fillC = fillC;
4665				cmMap_overlayColors['color_'+idColor].fillO = fillO;
4666				cmMap_overlayColors['color_'+idColor].name = colorName;
4667				cmMap_overlayColors['color_'+idColor].desc = colorDesc;
4668				cmMap_overlayColorsLength++;
4669			});
4670		}
4671	}
4672
4673    /**
4674     * Función que devuelve una cadena con los estilos de las formas permitidos en el proyecto
4675     * @param {string} idColor - Color
4676     * @returns {string}
4677     * @memberOf MapsApi
4678     */
4679	googleMapObject.cmMap_getOverlayColors=function(idColor){
4680		var overlayColors = '';
4681		for(var i in cmMap_overlayColors) {
4682			overlayColors += '<div id="'+cmMap_overlayColors[i].idColor+'" class="colorOverlay'+((idColor && idColor == cmMap_overlayColors[i].idColor)?' selected':'')+'" style="background-color:'+cmMap_overlayColors[i].strokeC+'" title="'+cmMap_overlayColors[i].name+'"></div>\n';
4683		}
4684		return overlayColors;
4685	}
4686
4687	/******************************************************************************************************
4688	Función que inicializa google maps
4689	*******************************************************************************************************/
4690    /**
4691	 * Función que inicializa google maps
4692     * @param mapContainer
4693     * @param kmlObject
4694     */
4695	googleMapObject.cmMap_initMap=function(mapContainer, kmlObject){
4696		if(!cmMap_ajaxResourcesLoaded) {
4697			$.ajax({
4698				url: cmMap_rootWeb+"/cm/"+cmMap_currentWeb+"/"+((wizardMode || $("body").hasClass("cmWizardEditMode"))?'wizard':'gmaps')+"/tkGMapsStyles",
4699				type: "POST",
4700				data: "locale="+cmMap_lang,
4701				dataType: $.browser.msie ? 'text' : 'xml',
4702				success: function(xml){
4703
4704					if(typeof(xml) == "string") xml = $.parseXML(xml);
4705
4706					var xmlResp = $(xml).find("response");
4707					if(xmlResp.length > 0 && xmlResp.attr("success") == "true") {
4708
4709						cmMap_iconMarkerList = $("markerList", xmlResp);
4710						cmMap_colorOverlayList = $("overlayList", xmlResp);
4711						cmMap_messages = $("properties", xmlResp);
4712
4713						googleMapObject.cmMap_loadMap(mapContainer, kmlObject);
4714
4715						cmMap_ajaxResourcesLoaded = true;
4716					}
4717				}
4718			});
4719		}
4720		else {
4721			googleMapObject.cmMap_loadMap(mapContainer, kmlObject);
4722		}
4723	}
4724
4725    /**
4726     * Función que inicializa google maps
4727     * @param mapContainer
4728     * @param kmlObject
4729     * @memberOf MapsApi
4730     */
4731	googleMapObject.cmMap_loadMap=function(mapContainer, kmlObject){
4732
4733		// Comprobamos si tenemos opciones especificas para el mapa actual
4734		var varLngCoordToSet = '', varLatCoordToSet = '', varZoomToSet = '';
4735		for(cmMap_defaultOption in cmMap_defaultOptions) {
4736			if(mapContainer.hasClass(cmMap_defaultOption) || mapContainer.parents().hasClass(cmMap_defaultOption)) {
4737				varLngCoordToSet = cmMap_defaultOptions[cmMap_defaultOption][0];
4738				varLatCoordToSet = cmMap_defaultOptions[cmMap_defaultOption][1];
4739				varZoomToSet = cmMap_defaultOptions[cmMap_defaultOption][2];
4740			}
4741		}
4742
4743		//mapContainerToLoad: div donde se carga el mapa
4744		//kmlToLoad:kml que carga el mapa
4745		//zoomToSet:zoom que queremos que tenga el mapa, si se deja vacio coge lo especifico del proyecto
4746		//latCoordToSet:coordenada de latitud donde se va a centrar el mapa, si se deja vacio coge lo especifico del proyecto
4747		//lngCoordToSet:coordenada de longitude donde se va a centrar el mapa, si se deja vacio coge lo especifico del proyecto
4748		var mapData = {
4749			mapContainerToLoad:mapContainer,
4750			kmlToLoad:kmlObject,
4751			zoomToSet:varZoomToSet,
4752			latCoordToSet:varLatCoordToSet,
4753			lngCoordToSet:varLngCoordToSet
4754		};
4755
4756		cmMap_objects.push(this);
4757
4758		// Función que si existe se ejecuta antes de inicializar un mapa
4759		if(typeof(beforeLoadMapCustomFunction) == 'function') {
4760			beforeLoadMapCustomFunction(this, mapData);
4761		}
4762
4763		// Si descomentamos la siguiente linea, para cargar los marcadores y colores por ajax habria que comentar las tres siguientes
4764		//googleMapObject.cmMap_loadIconMarkerList(googleMapObject.cmMap_loadColorOverlayList,mapData);
4765		googleMapObject.cmMap_processMessages(cmMap_messages);
4766		googleMapObject.cmMap_processIconMarkerList(cmMap_iconMarkerList);
4767		googleMapObject.cmMap_processColorOverlayList(cmMap_colorOverlayList);
4768		// Cargamos el mapa
4769		googleMapObject.cmMap_initialize(mapData);
4770	}
4771
4772    /**
4773     * Función que elimina espacios en una cadena
4774     * @param string - Cadena a procesar
4775     * @memberOf MapsApi
4776     */
4777	var cmMap_removeSpaces=function(string) {
4778		return string.split(' ').join('');
4779	}
4780
4781    /**
4782     * Función que trata de forma excepcional el valor descripción y devuelve el valor correcto en función de si es texto o html
4783     * @param xmlNode - Nodo
4784     * @returns {string}
4785     * @memberOf MapsApi
4786     */
4787	var cmMap_getOverlayDescriptionValue=function(xmlNode) {
4788		var returnValue = '';
4789		if(xmlNode.childNodes && xmlNode.childNodes.length > 0) {
4790			for(var cn=0; cn < xmlNode.childNodes.length; cn++) {
4791				if((xmlNode.childNodes[cn].nodeType == 3 || xmlNode.childNodes[cn].nodeType == 4) && xmlNode.childNodes[cn].nodeValue) {
4792					returnValue += xmlNode.childNodes[cn].nodeValue;
4793				} else {
4794					try{
4795						returnValue += cmMap_convertXMLToString(xmlNode.childNodes[cn]);
4796					}
4797					catch(e){
4798						if(xmlNode.childNodes[cn].nodeValue) {
4799							returnValue += xmlNode.childNodes[cn].nodeValue;
4800						}
4801					}
4802				}
4803			}
4804		}
4805		return returnValue;
4806	}
4807
4808    /**
4809     * Esta función convierte en una cadena el documento xml pasado como parámetro en función del navegador.
4810     * @param xmlDoc
4811     * @returns {string}
4812     * @memberOf MapsApi
4813     */
4814	var cmMap_convertXMLToString=function(xmlDoc) {
4815
4816		// all browsers, except IE before version 9
4817		if(window.DOMParser){
4818			var serializer = new XMLSerializer();
4819			var xmlString = serializer.serializeToString(xmlDoc);
4820			xmlString = xmlString.replace(/&amp;/g, '&');
4821			return xmlString;
4822		}
4823
4824		// Internet Explorer before version 9
4825		if (window.XMLSerializer) {
4826			return (new window.XMLSerializer()).serializeToString(xmlDoc);
4827		} else if (typeof xmlDoc.xml != "undefined") {
4828			return xmlDoc.xml;
4829		}
4830	}
4831
4832    /**
4833     * Función que elimina un elemento de un array
4834     * @param arrayFromDelete - Array al que hay que eliminar el elemento
4835     * @param idElement - Id del elemento a eliminar
4836     * @memberOf MapsApi
4837     */
4838	var cmMap_deleteElementFromArray=function(arrayFromDelete,idElement){
4839		var arrayAux=arrayFromDelete.splice(idElement,parseInt(arrayFromDelete.length-idElement));
4840		arrayAux.shift();
4841		return arrayFromDelete.concat(arrayAux);
4842		
4843	}
4844
4845    /**
4846     * Función que crea el formulario para de como llegar
4847     * @param {string} typeOfOverlay - Tipo de overlay
4848     * @param {string} idOverlay - Id
4849     * @memberOf MapsApi
4850     */
4851	var showHowToArrive=function(typeOfOverlay,idOverlay) {
4852		var _showMapFormContainer=$("div.showMapFormContainer");
4853		var _isRouteInMap=$("body.cmMap_googleMapsRoute").length>0?true:false;
4854		$("p.cmParagraph",_showMapFormContainer).html(resolveMessageinGmaps('{directionsTitle}').replace("{0}",cmMap_overlaysInMap[typeOfOverlay][idOverlay].name));
4855		$("body").addClass("showFormOnDemand");
4856		_showMapFormContainer.fadeIn(800);
4857		cmMap_oldInfoWindow.close();
4858
4859		// Contemplamos la posibilidad de anadir opciones personalizadas despues de mostrar el panel de direcciones
4860		if(typeof(cmMap_myCustomAfterShowDirections) == 'function') {
4861			cmMap_myCustomAfterShowDirections(googleMapObject);
4862		}
4863
4864		if(_isRouteInMap){
4865			// Le indicamos al mapa que ha sido cambiado de tamano
4866			googleMapObject.cmMap_resize();
4867			// Volvemos a centrar y establecer el zoom
4868			googleMapObject.cmMap_setCenterAndZoom();
4869		}
4870		
4871		$("form",_showMapFormContainer).unbind("submit").submit(function(){
4872			if(_isRouteInMap){
4873				cmMap_directionsDisplay.setMap(null);
4874				cmMap_directions.empty();
4875			}
4876			googleMapObject.cmMap_calculateCustomRoute(typeOfOverlay,idOverlay);
4877			return false;
4878		});
4879		
4880		$("#gmSearchResetButton",_showMapFormContainer).unbind("click").click(function(){
4881			if(_isRouteInMap){
4882				//eliminamos la ruta de como llegar e incluimos la ruta que existia
4883				cmMap_directions.empty();
4884				cmMap_directionsDisplay.setPanel(cmMap_directions.get(0));
4885				cmMap_customDirectionsDisplay.setMap(null);
4886				cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setMap(googleMapObject.cmMap);
4887				
4888				_showMapFormContainer.hide();
4889				$(this).hide();
4890				$("body").removeClass("showFormOnDemand");
4891				cmMap_directionsDisplay.setMap(googleMapObject.cmMap);
4892				google.maps.event.trigger(googleMapObject.cmMap, 'resize');
4893				googleMapObject.cmMap_fitBounds();
4894
4895			}else{
4896				_showMapFormContainer.hide();
4897				$("body").removeClass("showFormOnDemand");
4898				googleMapObject.cmMap_hideAddressPanel();
4899			}
4900			return false;
4901		});
4902	}
4903
4904    /**
4905     * Función que calcula la ruta al destino a partir de las coordenadas pasadas como parametro
4906     * @param {string} lat - Latitud
4907     * @param {string} lng - Longitud
4908     * @memberOf MapsApi
4909     */
4910	googleMapObject.cmMap_howToArriveFromLocation = function(lat, lng) {
4911		var _showMapFormContainer=$("div.showMapFormContainer");
4912		$("#cmMap_startAddressInput", _showMapFormContainer).val(lat+','+lng);
4913		$("form",_showMapFormContainer).submit();
4914	}
4915
4916    /**
4917     * Función que calcula la ruta al destino a partir de las coordenadas del marcador pasado como parametro
4918     * @param marker
4919     * @memberOf MapsApi
4920     */
4921	googleMapObject.cmMap_howToArriveJSON = function(marker) {
4922		var _showMapFormContainer=$("div.showMapFormContainer");
4923		$("#cmMap_startAddressInput", _showMapFormContainer).val(marker.position.lat()+','+marker.position.lng());
4924		$("form",_showMapFormContainer).submit();
4925	}
4926
4927    /**
4928     * Función que calcula la ruta de destino a partir de una dirección de origen introducida
4929     * @param typeOfOverlay
4930     * @param idOverlay
4931     * @memberOf MapsApi
4932     */
4933	googleMapObject.cmMap_calculateCustomRoute = function(typeOfOverlay,idOverlay) {
4934
4935		if(!cmMap_customDirectionsDisplay || !cmMap_customDirectionsService) {
4936			cmMap_customDirectionsDisplay = new google.maps.DirectionsRenderer({draggable: true});
4937			cmMap_customDirectionsService = new google.maps.DirectionsService();
4938		}
4939
4940		var _startAddress = document.getElementById("cmMap_startAddressInput").value;
4941		if(cmMap_overlaysInMap[typeOfOverlay].length > 0) {
4942			var _endAddress = cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.getPosition();
4943			var _dirRequest = {
4944				origin: _startAddress,
4945				destination: _endAddress,
4946				travelMode: google.maps.DirectionsTravelMode.DRIVING,
4947				unitSystem: google.maps.DirectionsUnitSystem.METRIC,
4948				provideRouteAlternatives: true,
4949				region: cmMap_region
4950			};
4951			cmMap_customDirectionsService.route(_dirRequest, function(response, status) {
4952				if (status == google.maps.DirectionsStatus.OK) {
4953					googleMapObject.cmMap_showAddressPanel();
4954					cmMap_overlaysInMap[typeOfOverlay][idOverlay].overlay.setMap(null);
4955					cmMap_customDirectionsDisplay.setMap(googleMapObject.cmMap);
4956					cmMap_customDirectionsDisplay.setPanel(cmMap_directions.get(0));
4957					cmMap_customDirectionsDisplay.setDirections(response);
4958				}
4959				else {
4960					if(googleMapObject.cmMap_editableMode) {
4961						messageBox(true,resolveMessageinGmaps('{notFindSourceAddress}'));
4962					}
4963					else {
4964						alert(resolveMessageinGmaps('{notFindSourceAddress}'));
4965					}
4966				}
4967			});
4968		}
4969	}
4970
4971    /**
4972     * Función que muestra la capa de direcciones de la ruta encontrada y adapta los tamaños
4973     * @memberOf MapsApi
4974     */
4975	googleMapObject.cmMap_showAddressPanel = function() {
4976
4977		$("body").addClass("cmMap_googleMapsRoute");
4978		cmMap_directions.show();
4979		$("#gmSearchResetButton").show();
4980
4981		// Contemplamos la posibilidad de anadir opciones personalizadas despues de mostrar el panel de direcciones
4982		if(typeof(cmMap_myCustomAfterShowDirections) == 'function') {
4983			cmMap_myCustomAfterShowDirections(googleMapObject);
4984		}
4985
4986		// Le indicamos al mapa que ha sido cambiado de tamano
4987		google.maps.event.trigger(googleMapObject.cmMap, 'resize');
4988	}
4989
4990    /**
4991     * Función que deja el mapa en su estado inicial
4992     * @memberOf MapsApi
4993     */
4994	googleMapObject.cmMap_hideAddressPanel = function() {
4995
4996		$("body").removeClass("cmMap_googleMapsRoute");
4997		cmMap_directions.hide();
4998		$("#cmMap_startAddressInput").val("");
4999		$("#gmSearchResetButton").hide();
5000
5001		// Contemplamos la posibilidad de anadir opciones personalizadas despues de ocultar el panel de direcciones
5002		if(typeof(cmMap_myCustomAfterHideDirections) == 'function') {
5003			cmMap_myCustomAfterHideDirections(googleMapObject);
5004		}
5005
5006		// Le indicamos al mapa que ha sido cambiado de tamano
5007		google.maps.event.trigger(googleMapObject.cmMap, 'resize');
5008		googleMapObject.cmMap.setOptions(myOptions);
5009		googleMapObject.cmMap_setCenterAndZoom();
5010
5011		cmMap_customDirectionsDisplay.setMap(null);
5012		cmMap_overlaysInMap['markerNotInRoute'][0].overlay.setMap(googleMapObject.cmMap);
5013	}
5014
5015    /**
5016     * Función que indica al mapa que ha sido redimensionado
5017     * @memberOf MapsApi
5018     */
5019	googleMapObject.cmMap_resize = function() {
5020		google.maps.event.trigger(googleMapObject.cmMap, 'resize');
5021	}
5022
5023    /**
5024     * Función que inicia el diálogo con los resultados de búsqueda en modo listado
5025     * @param {boolean} isContent
5026     * @param {string} contentName - Nombre
5027     * @returns {jQuery|HTMLElement}
5028     * @memberOf MapsApi
5029     */
5030	googleMapObject.cmMap_initResultsModalDialog = function(isContent, contentName) {
5031
5032		var $modalDialog = $("#cmMap_resultsModalDialog");
5033		if($modalDialog.length == 0) {
5034			$modalDialog = $('<div class="modal fade cmMap_resultsModalDialog" id="cmMap_resultsModalDialog" tabindex="-1" role="dialog" aria-labelledby="resultsModalDialogLabel" aria-hidden="true"> \
5035										<div class="modal-dialog modal-lg"> \
5036											<div class="modal-content"> \
5037												<div class="modal-header"> \
5038													<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> \
5039													<h1 class="modal-title h4" id="resultsModalDialogLabel">'+(!isContent?resolveMessageinGmaps('{searchResults}'):(resolveMessageinGmaps('{contentSearchResults}')+' "'+contentName+'"'))+'</h1> \
5040												</div> \
5041												<div class="modal-body"></div> \
5042												<div class="modal-footer"> \
5043													<button type="button" class="btn btn-default" data-dismiss="modal">'+resolveMessageinGmaps('{close}')+'</button> \
5044												</div> \
5045											</div> \
5046										</div> \
5047									</div>');
5048
5049			$("body").append($modalDialog);
5050
5051			$modalDialog.on('shown.bs.modal', function() {
5052				onLightboxShown($(this));
5053				afterShowModalDialog($(this));
5054			});
5055
5056			$modalDialog.on('hidden.bs.modal', function() {
5057				onLightboxHidden($(this));
5058				$(this).removeData("bs.modal").remove();
5059			});
5060		}
5061
5062		return $modalDialog;
5063
5064	}
5065
5066    /**
5067     * Función que carga en un diálogo los resultados de búsqueda en modo listado
5068     * @param $modalDialog - Dialogo
5069     * @param data - Datos
5070     * @param {string} _url - Url
5071     * @param _params - Parametros
5072     * @memberOf MapsApi
5073     */
5074	googleMapObject.cmMap_loadResultsModalDialog = function($modalDialog, data, _url, _params) {
5075
5076		if($modalDialog.length == 0 || data == null) return;
5077
5078		var dataHtml = $.trim(data.html);
5079		if(dataHtml != '') {
5080			if(data.navigation.totalLength > data.navigation.show) {
5081				var paginationHtml  = '<div class="row">\n';
5082					paginationHtml += '    <div class="col-md-12 text-center">\n';
5083					paginationHtml += '        <ul class="pagination">\n';
5084					if(data.navigation.actualPosition > 0) {
5085						paginationHtml += '            <li><a href="'+_url+'?'+_params+'&position.mappoints='+(data.navigation.actualPosition - data.navigation.show)+'&nshow.mappoints='+data.navigation.show+'"><span>'+resolveMessageinGmaps('{previous}')+'</span></a></li>';
5086					} else {
5087						paginationHtml += '            <li class="disabled"><span>'+resolveMessageinGmaps('{previous}')+'</span></li>';
5088					}
5089					paginationHtml += '            <li class="disabled"><span>'+resolveMessageinGmaps('{showing}')+' '+(data.navigation.actualPosition+1)+' - '+((data.navigation.actualPosition+data.navigation.show > data.navigation.totalLength)?data.navigation.totalLength:data.navigation.actualPosition+data.navigation.show)+' / '+resolveMessageinGmaps('{total}')+' '+data.navigation.totalLength+'</span></li>\n';
5090					if(data.navigation.actualPosition < data.navigation.totalLength - data.navigation.show) {
5091						paginationHtml += '            <li><a href="'+_url+'?'+_params+'&position.mappoints='+(data.navigation.actualPosition + data.navigation.show)+'&nshow.mappoints='+data.navigation.show+'"><span>'+resolveMessageinGmaps('{next}')+'</span></a></li>';
5092					} else {
5093						paginationHtml += '            <li class="disabled"><span>'+resolveMessageinGmaps('{next}')+'</span></li>';
5094					}
5095					paginationHtml += '        </ul>\n';
5096					paginationHtml += '    </div>\n';
5097					paginationHtml += '</div>\n';
5098				dataHtml += paginationHtml;
5099			}
5100
5101			$("div.modal-body", $modalDialog).html(dataHtml);
5102
5103			// Insertamos los eventos de paginacion
5104			$("ul.pagination > li > a", $modalDialog).bind("click", function(e) {
5105				e.preventDefault();
5106				var _href = $(this).attr("href");
5107
5108				$("div.modal-body", $modalDialog).html('<div class="spinner"><span class="fa fa-4x fa-refresh fa-spin"></span></div>');
5109
5110				$.ajax({
5111					dataType: "json",
5112					url: _href.split('?')[0],
5113					data: _href.split('?')[1],
5114					type: 'GET',
5115					success: function(data){
5116						if(data != null) {
5117							googleMapObject.cmMap_loadResultsModalDialog($modalDialog, data, _url, _params);
5118						}
5119					}
5120				});
5121			});
5122		} else {
5123			$("div.modal-body", $modalDialog).html('<p>'+resolveMessageinGmaps('{noResults}')+'</p>');
5124		}
5125	}
5126
5127    /**
5128     * Función que crea un menú de marcadores
5129     * @memberOf MapsApi
5130     */
5131	function cmMap_menu(){
5132		var menuMarcador=this;
5133		var menuContainer = $('<ul class="cmMap_Menu clearfix"></ul>');
5134		menuMarcador.cmMap_createMenu=function(){
5135
5136			var categoryNum=0;
5137			for (category in cmMap_MarkersInMapByCategory){
5138				categoryNum++;
5139			}
5140
5141			//si hay mas de una categoria o ademas hay rutas o zonas mostramos menu, si no no.
5142			if((categoryNum>1) || (categoryNum>0 &&(cmMap_overlaysInMap['polyline'].length>0 || cmMap_overlaysInMap['polygon'].length>0 || cmMap_overlaysInMap['route'].length>0))){
5143				$(googleMapObject.cmMap_container).append(menuContainer);
5144			}
5145			//creamos elementos de marcadores
5146			if(cmMap_overlaysInMap['markerNotInRoute'].length>0){
5147				menuMarcador.cmMap_createMarkerMenuItem();
5148			}
5149			
5150			if(cmMap_overlaysInMap['polyline'].length>0){
5151				menuMarcador.cmMap_createOverlayMenuItem('polyline');
5152			}
5153			
5154			if(cmMap_overlaysInMap['polygon'].length>0){
5155				menuMarcador.cmMap_createOverlayMenuItem('polygon');
5156			}
5157
5158			if(cmMap_overlaysInMap['markerInRoute'].length>0){
5159				menuMarcador.cmMap_createRouteMenuItem();
5160			}
5161			
5162		}
5163
5164		menuMarcador.cmMap_createRouteMenuItem=function(){
5165			menuContainer.append('<li class="cmMap_MenuItem cmMap_RouteMenuItem cmMap_MenuItemShow"><img src="'+cmMap_rootWeb+'/imagenes/contents/routeMenuItem.png" alt="" /><span class="cmMap_MenuText">'+resolveMessageinGmaps('{routesByCar}')+'</span></li>');
5166			
5167			$(".cmMap_RouteMenuItem",menuContainer).css({'cursor':'pointer'}).click(function(){
5168				menuMarcador.cmMap_toggleVisibilityRoute($(this));
5169			});
5170		}
5171
5172		menuMarcador.cmMap_createOverlayMenuItem=function(typeOfOverlay){
5173			var cmMap_MenuText = '';
5174			switch(typeOfOverlay) {
5175				case 'polyline':
5176					cmMap_MenuText = resolveMessageinGmaps('{line}');
5177					break;
5178				case 'polygon':
5179					cmMap_MenuText = resolveMessageinGmaps('{areas}');
5180					break;
5181				case 'rectangule':
5182					cmMap_MenuText = resolveMessageinGmaps('{rectangles}');
5183					break;
5184				case 'circle':
5185					cmMap_MenuText = resolveMessageinGmaps('{circles}');
5186					break;
5187			}
5188
5189			menuContainer.append('<li class="cmMap_MenuItem cmMap_'+typeOfOverlay+'MenuItem cmMap_MenuItemShow"><img src="'+cmMap_rootWeb+'/imagenes/contents/'+typeOfOverlay+'MenuItem.png" alt="" /><span class="cmMap_MenuText">'+cmMap_MenuText+'</span></li>');
5190			
5191			$(".cmMap_"+typeOfOverlay+"MenuItem",menuContainer).css({'cursor':'pointer'}).click(function(){
5192				menuMarcador.cmMap_toggleVisibilityOverlay($(this),typeOfOverlay);
5193			});
5194		}
5195
5196		menuMarcador.cmMap_createMarkerMenuItem=function(){
5197			var categoryNum=0;
5198			var contentMenu='';
5199			for (category in cmMap_MarkersInMapByCategory){
5200				contentMenu+='<li class="cmMap_MenuItem cmMap_MarkerMenuItem cmMap_MenuItemShow cmMap_MenuItem_'+category+'"><img src="'+cmMap_markerImages[category].markerIcon+'" alt="" /><span class="cmMap_MenuText">'+cmMap_markerImages[category].name+'</span></li>';
5201				categoryNum++;
5202			}
5203			//si hay mas de una categoria o ademas hay rutas o zonas mostramos menu, si no no.
5204			if((categoryNum>1) || (categoryNum>0 &&(cmMap_overlaysInMap['polyline'].length>0 || cmMap_overlaysInMap['polygon'].length>0 || cmMap_overlaysInMap['route'].length>0))){
5205				menuContainer.append(contentMenu);
5206				
5207				$(".cmMap_MarkerMenuItem",menuContainer).each(function(){
5208					$(this).css({'cursor':'pointer'}).click(function(){
5209						menuMarcador.cmMap_toggleVisibilityMarker($(this));
5210					});
5211				});
5212			}
5213		}
5214
5215		menuMarcador.cmMap_toggleVisibilityMarker= function(elem){
5216			var className = elem.attr("class");
5217			var regex = new RegExp('cmMap_MenuItem_([0-9A-Za-z_]+)');
5218			var results = regex.exec(className);
5219			if(results != null) {
5220				var categoryName = results[1];
5221			}
5222			if(elem.hasClass('cmMap_MenuItemShow')){
5223				cmMap_closeOldWindow();
5224				for(var i=0;i<cmMap_MarkersInMapByCategory[categoryName].length;i++){
5225					cmMap_MarkersInMapByCategory[categoryName][i].setMap(null);
5226				}
5227				elem.removeClass('cmMap_MenuItemShow').addClass('cmMap_MenuItemHide').fadeTo("fast", 0.33);
5228			}else{
5229				for(var i=0;i<cmMap_MarkersInMapByCategory[categoryName].length;i++){
5230					cmMap_MarkersInMapByCategory[categoryName][i].setMap(googleMapObject.cmMap);
5231				}
5232				elem.removeClass('cmMap_MenuItemHide').addClass('cmMap_MenuItemShow').fadeTo("fast", 1);
5233			}
5234		}
5235
5236		menuMarcador.cmMap_toggleVisibilityOverlay= function(elem,typeOfOverlay){
5237			if(elem.hasClass('cmMap_MenuItemShow')){
5238				cmMap_closeOldWindow();
5239				for(var i=0;i<cmMap_overlaysInMap[typeOfOverlay].length;i++){
5240					cmMap_overlaysInMap[typeOfOverlay][i].overlay.setMap(null);
5241				}
5242				elem.removeClass('cmMap_MenuItemShow').addClass('cmMap_MenuItemHide').fadeTo("fast", 0.33);
5243			}else{
5244				for(var i=0;i<cmMap_overlaysInMap[typeOfOverlay].length;i++){
5245					cmMap_overlaysInMap[typeOfOverlay][i].overlay.setMap(googleMapObject.cmMap);
5246				}
5247				elem.removeClass('cmMap_MenuItemHide').addClass('cmMap_MenuItemShow').fadeTo("fast", 1);
5248			}
5249		}
5250
5251		menuMarcador.cmMap_toggleVisibilityRoute= function(elem){
5252			if(elem.hasClass('cmMap_MenuItemShow')){
5253				cmMap_closeOldWindow();
5254				for(var i=0;i<cmMap_overlaysInMap['markerInRoute'].length;i++){
5255					cmMap_overlaysInMap['markerInRoute'][i].overlay.setMap(null);
5256				}
5257				for(var i=0;i<cmMap_overlaysInMap['route'].length;i++){
5258					cmMap_overlaysInMap['route'][i].overlay.setMap(null);
5259				}
5260				cmMap_directionsDisplay.setMap(null);
5261				elem.removeClass('cmMap_MenuItemShow').addClass('cmMap_MenuItemHide').fadeTo("fast", 0.33);
5262			}else{
5263				for(var i=0;i<cmMap_overlaysInMap['markerInRoute'].length;i++){
5264					cmMap_overlaysInMap['markerInRoute'][i].overlay.setMap(googleMapObject.cmMap);
5265				}
5266				for(var i=0;i<cmMap_overlaysInMap['route'].length;i++){
5267					cmMap_overlaysInMap['route'][i].overlay.setMap(googleMapObject.cmMap);
5268				}
5269				cmMap_directionsDisplay.setMap(googleMapObject.cmMap);
5270				elem.removeClass('cmMap_MenuItemHide').addClass('cmMap_MenuItemShow').fadeTo("fast", 1);
5271			}
5272		}
5273	}
5274
5275	/**
5276     * Función que crea botones customizados para el zoom del mapa
5277     * @param controlDiv - Capa donde vamos a insertar los controles
5278     * @param map - Mapa de Google Maps
5279     * @memberOf MapsApi
5280     */
5281	function cmMap_customZoom(controlDiv, map) {
5282		// Creamos los controles y los insertamos en el mapa 
5283		var $controlUIzoomIn = $('<button id="control-zoom-in" type="button"> \
5284									<span class="fa fa-plus" aria-hidden="true"></span> \
5285									<span class="sr-only">'+zoomIn+'</span> \
5286		  						</button>');
5287		var $controlUIzoomOut = $('<button id="control-zoom-out" type="button"> \
5288									<span class="fa fa-minus" aria-hidden="true"></span> \
5289									<span class="sr-only">'+zoomOut+'</span> \
5290								  </button>');
5291								  
5292	  	controlDiv.append($controlUIzoomIn);
5293	  	controlDiv.append($controlUIzoomOut);
5294		  
5295		// Añadimos listener al clickar sobre los controles para aumentar o disminuir
5296		google.maps.event.addDomListener($controlUIzoomIn[0], 'click', function() {
5297		    map.setZoom(map.getZoom()+1)
5298		});
5299		google.maps.event.addDomListener($controlUIzoomOut[0], 'click', function() {
5300		    map.setZoom(map.getZoom()-1)
5301		});
5302	}
5303
5304	/**
5305     * Funcion que crea boton customizado para el selector de tipo de mapa
5306     * @param controlDiv - Capa donde vamos a insertar el control
5307     * @param map - Mapa de Google Maps
5308     * @memberOf MapsApi
5309     */
5310	function cmMap_customType(controlDiv, map) {
5311		// Creamos los controles y los insertamos en el mapa 
5312		var $typeSelector = $('<button id="button-type" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> \
5313									<span>'+typeControlTitle+'</span> \
5314									<span class="caret"></span> \
5315								</button> \
5316								<ul class="dropdown-menu" aria-labelledby="button-type"> \
5317									<li> \
5318										<button id="roadmap" class="active" type="button"> \
5319											<span class="fa fa-check" aria-hidden="true"></span> \
5320											<span class="type">'+roadmap+'</span> \
5321										</button> \
5322									</li> \
5323									<li> \
5324										<button id="satellite" type="button"> \
5325											<span class="fa fa-check" aria-hidden="true"></span> \
5326											<span class="type">'+satellite+'</span> \
5327										</button> \
5328									</li> \
5329									<li> \
5330										<button id="hybrid" type="button"> \
5331											<span class="fa fa-check" aria-hidden="true"></span> \
5332											<span class="type">'+hybrid+'</span> \
5333										</button> \
5334									</li> \
5335									<li> \
5336										<button id="terrain" type="button"> \
5337											<span class="fa fa-check" aria-hidden="true"></span> \
5338											<span class="type">'+terrain+'</span> \
5339										</button> \
5340									</li> \
5341								</ul>');
5342								  
5343	  	controlDiv.append($typeSelector);
5344		  
5345		// Añadimos listener al clickar sobre los controles
5346		$typeSelector.find('button').each(function() {
5347			var $currentElement = $(this);
5348			var idType = $currentElement.attr("id");
5349			google.maps.event.addDomListener($currentElement[0], 'click', function() {
5350				map.setMapTypeId(idType);
5351				$typeSelector.find('button').removeClass('active');
5352				$currentElement.addClass('active');
5353			});
5354		});
5355	}
5356}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.