

	console.log('Define: setMapMarkers(_markers);');
	function setMapMarkers(_markers){
		console.log('Call: setMapMarkers(_markers);', _markers);
		if (window['googlemap']) {
			googlemap.replaceMarkers(_markers);
		} else {
			setTimeout(function() {
				setMapMarkers(_markers);
			}, 100);
		}
	}

	console.log('Define: setMapPolylines(_polylines);');
	function setMapPolylines(_polylines){
		console.log('Call: setMapPolylines(_polylines);', _polylines);
		if (window['googlemap']) {
			googlemap.replacePolylines(_polylines);
		} else {
			setTimeout(function() {
				setMapPolylines(_polylines);
			}, 100);
		}
	}

	console.log('Define: createMap(map_id);');
	function createMap(map_id){
		console.log('Call: createMap('+map_id+');');

		if(map_id == undefined){
			console.log('No \'map_id\', exit createMap(map_id).');
			return;
		}

		if(!jQuery.isFunction(window.getMapOptions)){
			console.log('\'getMapOptions(map_id)\' ain\'t ready, exit createMap(map_id).');
			return;
		}
		var map_options      = getMapOptions(map_id);
	//	console.log('map_options', map_options);

		if((typeof google)=='undefined'){
			document.getElementById(map_options.map.id).innerHTML = '@create' + map_options.map.note;
			return;
		}

		var current_info_window = null;
		var current_marker = null;

		var mapOptions = {
			streetViewControl: map_options.streetview,
			zoom:              map_options.zoom,
			mapTypeId:         google.maps.MapTypeId[map_options.map.type]
		}

		switch(map_options.map.type_control){
			case 0:
				Object.assign(mapOptions, {
					mapTypeControl: false
				});
				break;
			case 1:
				Object.assign(mapOptions, {
					mapTypeControlOptions: {
						mapTypeIds: [
							google.maps.MapTypeId.ROADMAP,
							google.maps.MapTypeId.SATELLITE,
							google.maps.MapTypeId.TERRAIN
						]
					}
				});
				break;
			case 2:
				Object.assign(mapOptions, {
					mapTypeControlOptions: {
						mapTypeIds: [
							google.maps.MapTypeId.ROADMAP,
							google.maps.MapTypeId.SATELLITE,
							google.maps.MapTypeId.HYBRID,
							google.maps.MapTypeId.TERRAIN
						]
					}
				});
				break;
			default:
				Object.assign(mapOptions, {
					mapTypeControlOptions: {
						style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
					}
				});
				break;
		}

		switch(map_options.map.overview_control){
			case 1:
				Object.assign(mapOptions, {
					overviewMapControl: true,
					overviewMapControlOptions:{
						opened: false
					}
				});
				break;
			case 2:
				Object.assign(mapOptions, {
					overviewMapControl: true,
					overviewMapControlOptions:{
						opened: true
					}
				});
				break;
			default:
				break;
		}

		switch(map_options.map.scale_control){
			case 0:
				Object.assign(mapOptions, {
					zoomControl: false
				});
				break;
			default:
				Object.assign(mapOptions, {
					zoomControl: true,
					zoomControlOptions:{
						style: google.maps.ZoomControlStyle.LARGE
					}
				});
				break;
		}

		var map     = new google.maps.Map(document.getElementById(map_options.map.id), mapOptions);

		var bounds  = new google.maps.LatLngBounds();
		window.googlemap = {
			map: map,
			markers: [],
			polylines: [],

			createMarker: function(_marker){
				var marker = null;
				marker = new google.maps.Marker({
					id: _marker.id,
					data: _marker,
					map: this.map,
					position: new google.maps.LatLng(_marker.lat,_marker.lng)
				});

				if(_marker.relations        != undefined
				&& _marker.relations.length  > 0){
					marker.polylines = [];
					_marker.relations.forEach(function(relation){
						if(relation.valid == 1){
							marker.polylines.push(new google.maps.Polyline({
								path: [
									marker.position,
									{
										lat: parseFloat(relation.latitude),
										lng: parseFloat(relation.longitude)
									}
								],
								geodesic:      relation.geodesic       || true,
								strokeColor:   relation.stroke_color   || '#000000',
								strokeOpacity: relation.stroke_opacity || 1.0,
								strokeWeight:  relation.stroke_weight  || 1.0
							}));
						}
					});
				}

				if(_marker.title){
					marker.setTitle(_marker.title);
				}

				if(_marker.icon){
					marker.setIcon(_marker.icon);
				} else {
					marker.setIcon(map_options.protocoll+'://maps.gstatic.com/mapfiles/ms/micons/'+(_marker.color || 'blue')+'-dot.png');
					marker.setShadow({
						url: map_options.protocoll+'://maps.gstatic.com/mapfiles/shadow50.png',
						anchor: new google.maps.Point(10, 34)
					});
				}

			//	Draggable
				if(_marker.draggable){
					marker.setDraggable(true);
					marker.addListener('dragend', function(){
						if(_marker.target != undefined){
							var lat = document.getElementById(_marker.target.lat);
							if(lat){
								if(lat.type == "text"){
									lat.value = marker.getPosition().lat();
								} else {
									lat.innerHTML = marker.getPosition().lat();
								}
							}
							var lng = document.getElementById(_marker.target.lng);
							if(lng){
								if(lng.type == "text"){
									lng.value = marker.getPosition().lng();
								} else {
									lng.innerHTML = marker.getPosition().lng();
								}
							}
						} else {
							var elm = document.getElementById(_marker.target);
							if(elm){
								if(elm.type == "text"){
									elm.value = marker.getPosition().lat() + ", " + marker.getPosition().lng();
								} else {
									elm.innerHTML = marker.getPosition().lat() + ", " + marker.getPosition().lng();
								}
							}
						}
					});
				} else {
					marker.setDraggable(false);
				}

				if(_marker.info
				&& _marker.info.content){
					marker.infoWindow = new google.maps.InfoWindow({
						content: _marker.info.content,
					});

					marker.infoWindow.addListener('closeclick', function(){
						if(current_marker.polylines        != undefined
						&& current_marker.polylines.length  > 0){
							current_marker.polylines.forEach(function(polyline){
								polyline.setMap(null);
							});
						}
					});

					if( map_options.listeners.marker != undefined
					&&	map_options.listeners.marker.click != undefined){
						marker.addListener('click', function(){
							var listener = map_options.listeners.marker.click;
							window[listener](marker);
						});
					}

					marker.addListener('click', function(){
						if(map_options.info_window.auto_close){
							if(current_info_window != null){
								if(current_marker.polylines        != undefined
								&& current_marker.polylines.length  > 0){
									current_marker.polylines.forEach(function(polyline){
										polyline.setMap(null);
									});
								}
								current_info_window.close();
							}
							current_info_window = marker.infoWindow;
							current_marker = marker;
						}

						if(marker.polylines        != undefined
						&& marker.polylines.length  > 0){
							var outer_map = this.map;
							marker.polylines.forEach(function(polyline){
								polyline.setMap(outer_map)
							});
						}
						marker.infoWindow.open(this.map, marker);
					});
					if(_marker.info.show
					&& map_options.info_window.auto_close){
						marker.infoWindow.open(this.map, marker);
					}
				}
				return(marker);
			},

			replaceMarkers: function(_markers){
			//	Alte Marker entfernen
				for (var i = 0; i < this.markers.length; i++){
					this.markers[i].setMap(null);
				}
				this.markers = [];
				if(! (bunchHandler == null)){
				//	console.log('clearMarkers');
					bunchHandler.clearMarkers();
				}

				if(_markers        != null
				&& _markers.length  > 0){
					for (var i = 0; i < _markers.length; i++){
						var marker = this.createMarker(_markers[i]);
						this.markers.push(marker);
						if(! (bunchHandler == null)){
						//	console.log('add marker');
							bunchHandler.addMarker(marker);
						}
						bounds.extend(marker.getPosition());
					}
				}
			},

			createPolyline: function(_polyline){
				var polyline = new google.maps.Polyline({
				/*
					path: [
						{lat:<x0>, lng:<y0>},
						{lat:<x1>, lng:<y1>},
						{lat:<x2>, lng:<y2>},
						{lat:<x3>, lng:<y3>}
					]
				*/
					path:          _polyline.path           || [],
					geodesic:      _polyline.geodesic       || true,
					strokeColor:   _polyline.stroke_color   || '#000000',
					strokeOpacity: _polyline.stroke_opacity || 1.0,
					strokeWeight:  _polyline.stroke_weight  || 1.0
				});
				return(polyline)
			},

			replacePolylines: function(_polylines){
			//	Alte Polylines entfernen
				for (var i = 0; i < this.polylines.length; i++){
					this.polylines[i].setMap(null);
				}
				this.polylines = [];

				if(_polylines        != null
				&& _polylines.length  > 0){
					for (var i = 0; i < _polylines.length; i++){
						var polyline = this.createPolyline(_polylines[i]);
						polyline.setMap(this.map)
						this.polylines.push(polyline);
					}
				}
			}
		};

		var bunchHandler = null;
		switch(map_options.map.BunchHandler){
			case 'spiderfier':
				bunchHandler = new OverlappingMarkerSpiderfier(map, {
					markersWontMove: true,
					markersWontHide: true,
					basicFormatEvents: true
				});
				break;
			case 'clusterer':
				bunchHandler = new MarkerClusterer(map, googlemap.markers, {
					imagePath: '/global_files/javascript/google/maps/markerclusterer/images/m'
				});

				console.log(bunchHandler);
				break;
			case 'clustererplus':
				bunchHandler = new MarkerClusterer(map, googlemap.markers, {
					imagePath: '/global_files/javascript/google/maps/markerclustererplus/images/m'
				});
				break;
			default:
				break;
		}

	//	Add initial Markers
		if(map_options.initial_markers.length  > 0){
			setMapMarkers(map_options.initial_markers)
		}

	//	Add initial Polylines
		if(map_options.initial_polylines.length  > 0){
			setMapPolylines(map_options.initial_polylines)
		}

	//	Set Viewport to Show all Markers
		if(map_options.map.fitbounds){
			if (googlemap.markers.length != 0){
				if (googlemap.markers.length > 1){
					map.fitBounds(bounds);
					map.panToBounds(bounds);
				} else {
					map.panTo(bounds.getCenter());
				}
			}
		}
	}

