/** * Created by mhirdes on 27.11.13. */ (function ($) { var GoMapsExt = window.GoMapsExt = window.GoMapsExt || {}; GoMapsExt.Data = { mapSettings: { markerSearch: null, defaultZoom: null, doubleClickZoom: null, scrollZoom: null, panControl: null, scaleControl: null, streetviewControl: null, zoomControl: null, zoomControlType: null, defaultType: null, mapTypeControl: null, mapTypes: null, showRoute: null, calcRoute: null, styledMapName: null, styledMapCode: null, tooltipTitle: null, kmlUrl: null, kmlLocal: null, showForm: null }, zoomTypes: [], defaultMapTypes: [], addresses: [] }; /** * Controller for Map functionality * * @param {HTMLElement} element * @param {GoMapsExt.Data} gme * @constructor */ GoMapsExt.Controller = function (element, gme) { var $element = this.element = $(element); this.gme = gme; this.data = gme; this.route = []; this.infoWindow = new google.maps.InfoWindow(); this.bounds = new google.maps.LatLngBounds(); this.markers = []; this.map = new google.maps.Map(document.getElementById(gme.mapSettings.id), this._createMapOptions()); this._initializeCss(); this._initializeData(); this._initializeKmlImport(); this._initializeSearch(); this._initializeBackendAddresses(); this._initializeRoute(); this._initializeResizeListener(); this._initializeCheckboxListener(); this._initializeAddressListener(); // open info window window.setTimeout(function () { $element.trigger("openinfo"); }, 2000); this.setCategoriesFromRequest(); this.focusAddressFromRequest(); // trigger mapcreated on map $element.trigger("mapcreated"); this.refreshMap($element, gme); }; GoMapsExt.Controller.prototype = { // categories checkboxes setCategories: function (selectedCats) { var $element = this.element; $.each(this.markers, function (key, marker) { marker.setVisible(false); $.each(marker.categories, function (keyM, category) { if ($.inArray(category, selectedCats) != -1) { marker.setVisible(true); return true; } }); }); if ($element.markerCluster) { $element.markerCluster.repaint(); } }, setCategoriesFromRequest: function () { // set categories var getCats = this.getURLParameter('tx_gomapsext_show\\[cat\\]'); if (getCats) { getCats = getCats.split(","); this.setCategories(getCats); $('.js-gme-cat').each(function (key, checkbox) { if ($.inArray($(checkbox).val(), getCats) != -1) { $(checkbox).attr('checked', true); return true; } }); } }, focusAddressFromRequest: function () { var getAddress = this.getURLParameter('tx_gomapsext_show\\[address\\]'), $element = this.element, gme = this.data; if (getAddress) { this.focusAddress(getAddress, $element, gme); } }, // add a point addMapPoint: function (pointDescription, Route, $element, infoWindow, gme) { var _this = this, latitude = pointDescription.latitude, longitude = pointDescription.longitude; Route.push(pointDescription.address); if (Math.round(latitude) == 0 && Math.round(longitude) == 0) { $element.data("geocoder").geocode({"address": pointDescription.address}, function (point, status) { latitude = point[0].geometry.location.lat(); longitude = point[0].geometry.location.lng(); var position = new google.maps.LatLng(latitude, longitude); _this.setMapPoint(pointDescription, Route, $element, infoWindow, position, gme); }); return; } var position = new google.maps.LatLng(latitude, longitude); this.setMapPoint(pointDescription, Route, $element, infoWindow, position, gme); }, focusAddress: function (addressUid, $element, gme) { var _this = this; $.each(this.markers, function (key, marker) { if (marker.uid == addressUid) { $element.data("center", marker.position); if (marker.infoWindow) { marker.infoWindow.setContent(marker.infoWindowContent); marker.infoWindow.open(_this.map, marker); } _this.refreshMap($element, gme); return true; } }); if ($element.markerCluster) { $element.markerCluster.repaint(); } }, /** * decode URL Parameter go_maps_ext[cat] * * @param name * @returns {string|null} */ getURLParameter: function (name) { var uri = decodeURI(location.search); return (new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(uri) || ["", ""])[1].replace(/\+/g, '%20') || null; }, /** * get the travel mode * * @param $travelMode * @returns {string} */ getTravelMode: function ($travelMode) { var travelMode = google.maps.TravelMode.DRIVING; switch ($travelMode) { case 2: travelMode = google.maps.TravelMode.BICYCLING; break; case 3: travelMode = google.maps.TravelMode.TRANSIT; break; case 4: travelMode = google.maps.TravelMode.WALKING; break; } return travelMode; }, /** * get the unit system * * @param $unitSystem * @returns {number} */ getUnitSystem: function ($unitSystem) { var unitSystem = 0; switch ($unitSystem) { case 2: unitSystem = google.maps.UnitSystem.METRIC; break; case 3: unitSystem = google.maps.UnitSystem.IMPERIAL; break; } return unitSystem; }, /** * insert the point on the map * * @param pointDescription * @param Route * @param $element * @param infoWindow * @param position * @param gme */ setMapPoint: function (pointDescription, Route, $element, infoWindow, position, gme) { var _map = this.map, markerOptions = { position: position, map: _map, title: pointDescription.title }; if (pointDescription.marker != "") { if (pointDescription.imageSize == 1) { var Icon = { url: pointDescription.marker, size: new google.maps.Size(pointDescription.imageWidth * 2, pointDescription.imageHeight * 2), scaledSize: new google.maps.Size(pointDescription.imageWidth, pointDescription.imageHeight), origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(pointDescription.imageWidth / 2, pointDescription.imageHeight) }; var Shape = { type: 'rect', coord: [0, 0, pointDescription.imageWidth, pointDescription.imageHeight] }; var anchorPoint = new google.maps.Point(0, -pointDescription.imageHeight); $.extend(markerOptions, {icon: Icon, shape: Shape, anchorPoint: anchorPoint}); } else { $.extend(markerOptions, {icon: pointDescription.marker}); } } var marker = new google.maps.Marker(markerOptions); if (gme.mapSettings.markerCluster == 1) { google.maps.event.addListener(marker, 'visible_changed', function () { if (marker.getVisible()) { $element.markerCluster.addMarker(marker, true); } else { $element.markerCluster.removeMarker(marker, true); } }); } if (pointDescription.infoWindowContent != "" || pointDescription.infoWindowLink > 0) { var infoWindowContent = pointDescription.infoWindowContent; if (pointDescription.infoWindowLink > 0) { var daddr = (pointDescription.infoWindowLink == 2) ? pointDescription.latitude + ", " + pointDescription.longitude : pointDescription.address; daddr += " (" + pointDescription.title + ")"; infoWindowContent += '
' + infoWindowContent + '
'; if (pointDescription.openByClick) { google.maps.event.addListener(marker, "click", function () { if (!infoWindow.getMap() || gme.infoWindow != this.getPosition()) { infoWindow.setContent(infoWindowContent); infoWindow.open(_map, this); gme.infoWindow = this.getPosition(); } }); } else { google.maps.event.addListener(marker, "mouseover", function () { if (!infoWindow.getMap() || gme.infoWindow != this.getPosition()) { infoWindow.setContent(infoWindowContent); infoWindow.open(_map, this); gme.infoWindow = this.getPosition(); } }); } if (!pointDescription.closeByClick) { google.maps.event.addListener(marker, "mouseout", function () { infoWindow.close(); }); } if (pointDescription.opened) { $element.off("openinfo").on("openinfo", function () { infoWindow.setContent(infoWindowContent); infoWindow.open(_map, marker); }); gme.infoWindow = marker.getPosition(); } infoWindow.setContent(infoWindowContent); marker.infoWindowContent = infoWindowContent; marker.infoWindow = infoWindow; } marker.categories = pointDescription.categories.split(","); marker.uid = pointDescription.uid; this.markers.push(marker); this.bounds.extend(position); }, resize: function() { var _map = this.map, gme = this.data; google.maps.event.trigger(_map, 'resize'); _map.fitBounds(this.bounds); if (gme.mapSettings.zoom > 0) { _map.setZoom(gme.mapSettings.zoom); } this.refreshMap(this.element, gme); google.maps.event.trigger(this.infoWindow, 'content_changed'); }, /** * Set zoom, center and cluster * * @param $element * @param gme */ refreshMap: function ($element, gme) { var _map = this.map; if (gme.mapSettings.zoom > 0 || gme.addresses.length == 1) { google.maps.event.addListener(_map, "zoom_changed", function () { var zoomChangeBoundsListener = google.maps.event.addListener(_map, "bounds_changed", function () { if (this.initZoom == 1) { this.setZoom((gme.mapSettings.zoom > 0) ? gme.mapSettings.zoom : gme.mapSettings.defaultZoom); this.initZoom = 0; } google.maps.event.removeListener(zoomChangeBoundsListener); }); }); _map.initZoom = 1; } if ($element.data("center")) { _map.setCenter($element.data("center")); } else { _map.fitBounds(this.bounds); } this.refreshCluster($element, gme); }, /** * refresh the cluster * * @param $element * @param gme */ refreshCluster: function ($element, gme) { if (gme.mapSettings.markerCluster == 1) { if ($element.markerCluster != null) { $element.markerCluster.clearMarkers(); } $element.markerCluster = new MarkerClusterer(this.map, this.markers, { imagePath: 'https://googlemaps.github.io/js-marker-clusterer/images/m', styles: gme.mapSettings.markerClusterStyle, maxZoom: gme.mapSettings.markerClusterZoom, gridSize: gme.mapSettings.markerClusterSize }); } }, _initializeCss: function () { this.element .css("width", this.gme.mapSettings.width) .css("height", this.gme.mapSettings.height); }, _initializeData: function () { var $element = this.element, gme = this.data, _map = this.map; $element.data("map", _map); // styled map if (gme.mapSettings.styledMapName) { var myStyle = gme.mapSettings.styledMapCode, styledMapOptions = { name: gme.mapSettings.styledMapName, alt: gme.mapSettings.tooltipTitle }, myMapType = new google.maps.StyledMapType( myStyle, styledMapOptions ); _map.mapTypes.set(gme.mapSettings.styledMapName, myMapType); } if (gme.mapSettings.defaultType == 3 && gme.mapSettings.styledMapName) { _map.setMapTypeId(gme.mapSettings.styledMapName); } }, _createMapOptions: function () { var gme = this.gme; return { zoom: gme.mapSettings.defaultZoom, minZoom: gme.mapSettings.minZoom, maxZoom: gme.mapSettings.maxZoom, center: new google.maps.LatLng(0, 0), draggable: gme.mapSettings.draggable, disableDoubleClickZoom: gme.mapSettings.doubleClickZoom, scrollwheel: gme.mapSettings.scrollZoom, panControl: gme.mapSettings.panControl, scaleControl: gme.mapSettings.scaleControl, streetViewControl: gme.mapSettings.streetviewControl, zoomControl: gme.mapSettings.zoomControl, zoomControlOptions: {style: gme.zoomTypes[gme.mapSettings.zoomControlType]}, mapTypeId: gme.defaultMapTypes[gme.mapSettings.defaultType], mapTypeControl: gme.mapSettings.mapTypeControl, mapTypeControlOptions: {mapTypeIds: gme.mapSettings.mapTypes} }; }, _initializeKmlImport: function () { var _this = this, _map = this.map, gme = this.data, Route = this.route, $element = this.element; // KML import if (gme.mapSettings.kmlUrl != '' && gme.mapSettings.kmlLocal == 0) { var kmlLayer = new google.maps.KmlLayer(gme.mapSettings.kmlUrl, {preserveViewport: gme.mapSettings.kmlPreserveViewport}); kmlLayer.setMap(_map); } // KML import local if (gme.mapSettings.kmlUrl != '' && gme.mapSettings.kmlLocal == 1) { $.get(gme.mapSettings.kmlUrl, function (data) { //loop through placemarks tags $(data).find("Placemark").each(function () { //get coordinates and place name var coords = $(this).find("coordinates").text(), place = $(this).find("name").text(), description = $(this).find("description").text(), c = coords.split(","), address = { title: place, latitude: c[1], longitude: c[0], address: place, marker: '', imageSize: 0, imageWidth: 0, imageHeight: 0, infoWindowContent: description, infoWindowLink: 0, openByClick: 1, closeByClick: 1, opened: 0, categories: '' }; _this.addMapPoint(address, Route, $element, infoWindow, gme); gme.addresses.push(address); }); }); } }, _initializeSearch: function () { var _this = this, gme = this.data, $element = this.element; // Search if (gme.mapSettings.markerSearch == 1) { var $myForm = $('#' + gme.mapSettings.id + '-search'), searchIn = $myForm.find('.js-gme-sword'); $myForm.find('.js-gme-error').hide(); $myForm.submit(function () { var submitValue = $(searchIn).val().toLowerCase(); var notFound = true; $.each(gme.addresses, function (i, address) { $.each(address, function (index, val) { if (typeof val == "string" && (index == "title" || index == "infoWindowContent") && submitValue != "") { if (val.toLowerCase().indexOf(submitValue) != -1) { _this.focusAddress(_this.markers[i].uid, $element, gme); notFound = false; } } }); }); $myForm.find('.js-gme-error').toggle(notFound); return false; }); } }, _initializeBackendAddresses: function () { var _this = this, gme = this.data, $element = this.element, Route = this.route, infoWindow = this.infoWindow; // Add backend addresses if (gme.mapSettings.showRoute == 0) { $element.data("geocoder", new google.maps.Geocoder()); if ($element.data("geocoder")) { $.each(gme.addresses, function (index, address) { _this.addMapPoint(address, Route, $element, infoWindow, gme); }); } } }, _initializeRoute: function () { var _this = this, _map = this.map, gme = this.data, $element = this.element; // init Route function if (gme.mapSettings.showRoute == 1 || gme.mapSettings.calcRoute == 1) { var panelHtml = $('
<\/div>'), directionsService = new google.maps.DirectionsService(), directionsDisplay = new google.maps.DirectionsRenderer(); panelHtml.insertAfter($element); var renderRoute = function ($start, $end, $travelMode, $unitSystem) { var unitSystem = _this.getUnitSystem($unitSystem), request = { origin: $start, destination: $end, travelMode: _this.getTravelMode($travelMode) }; directionsDisplay.setMap(_map); directionsDisplay.setPanel(document.getElementById("dPanel-" + gme.mapSettings.id)); if (unitSystem != 0) { request.unitSystem = unitSystem; } directionsService.route(request, function (response, status) { if (status == google.maps.DirectionsStatus.OK) { directionsDisplay.setDirections(response); } else { alert(gme.ll.alert); } }); }; } // show route from backend if (gme.mapSettings.showRoute == 1) { renderRoute(gme.addresses[0].address, gme.addresses[1].address, gme.mapSettings.travelMode, gme.mapSettings.unitSystem); } // show route from frontend if (gme.mapSettings.showForm == 1) { var $mapForm = $('#' + gme.mapSettings.id + '-form'); $mapForm.submit(function () { var formStartAddress = $mapForm.find('.js-gme-saddress').val(), endAddressIndex = $mapForm.find('.js-gme-eaddress option:selected').val(), formEndAddress = endAddressIndex ? gme.addresses[parseInt(endAddressIndex)].address : gme.addresses[0].address, formTravelMode = $mapForm.find('.js-gme-travelmode').val(), formUnitSystem = $mapForm.find('.js-gme-unitsystem').val(); if (formStartAddress == null) { formStartAddress = gme.addresses[0].address; formEndAddress = gme.addresses[1].address; } if (formTravelMode == null) { formTravelMode = gme.mapSettings.travelMode; } else { formTravelMode = parseInt(formTravelMode); } if (formUnitSystem == null) { formUnitSystem = gme.mapSettings.unitSystem; } else { formUnitSystem = parseInt(formUnitSystem); } renderRoute(formStartAddress, formEndAddress, formTravelMode, formUnitSystem); return false; }); } }, _initializeResizeListener: function () { var _this = this; // eventHandler resize can be used this.element.bind('mapresize', function () { _this.resize(); }); }, _initializeCheckboxListener: function () { var _this = this; // categories checkboxes $('.js-gme-cat').change(function () { var selectedCats = $('.js-gme-cat:checked').map(function () { return this.value; }); _this.setCategories(selectedCats); }); }, _initializeAddressListener: function () { var _this = this, $element = this.element, gme = this.gme; $('.js-gme-address').click(function () { var selectedAddress = [$(this).attr('data-address')]; _this.focusAddress(selectedAddress, $element, gme); return false; }); } }; // create a new Google Map $.fn.gomapsext = function (gme) { var $element = $(this); if (!$element.data('gomapsextcontroller')) { $element.data('gomapsextcontroller', new GoMapsExt.Controller($element, gme)); } }; }(jQuery));