Hi Gerhard,
yes it was really helpful! Thanks to your post I managed to do what I needed and I love the draggable marker for fine tuning!
I mixed your code with
this one that checks if coords are inside a circle through GoogleMaps API. For country and region fields I’m using Dynamic Cascade plugin with imported Virtuemart country/region tables (#__countries, #__states) in database.
This is the code now I’m using in my mainbody.php override.
<?php
// No Direct Access
defined( '_JEXEC' ) or die;
$document = JFactory::getDocument();
$document->addScript( 'http://maps.googleapis.com/maps/api/js?sensor=false' ); // Google Maps JS
$buttonText = 'Verify Geodata'; // Button text
?>
<script type="text/javascript">
/* Display a Google Map and pinpoint a location */
(function($) {
$(document).ready(function() {
var map = $('#map_canvas'); // Map canvas
var lat = $('#art_map_latitude'); // Post latitude
var lng = $('#art_map_longitude'); // Post longitude
var defaultLat = $('#art_user_latitude :selected').text(); // User latitude
var defaultLng = $('#art_user_longitude :selected').text(); // User longitude
var street = $('#art_map_street'); // Address
var postcode = $('#art_map_zip'); // Postcode
var city = $('#art_map_city'); // City
var countryList = $('#art_map_country').change(function() { // Country list
var countryVal = $('option:selected', this).text();
if (countryVal == '- Select an Option') { $('#art_map_country_select').val(' ');}
else { $('#art_map_country_select').val(countryVal);} }).change();
var country = $('#art_map_country_select'); // Country
var regionList = $('#art_map_region').change(function() { // Region list
var regionVal = $('option:selected', this).text();
if (regionVal == '- Select an Option -') { $('#art_map_region_select').val(' ');}
else { $('#art_map_region_select').val(regionVal);} }).change();
var region = $('#art_map_region_select'); // Region
var notes = $('#notes'); // Messages
var zoom = 8; // Zoom level
var infoWindow = '<span class="icon-map-marker"> Your post location</span>'; // Marker info window
var messageTrue = '<span class="icon-map-marker" style="color:green"> Geolocalization successful!</span>'; // Success message
var messageFalse = '<span class="icon-map-marker" style="color:red"> Geolocalization failed. Please select another location.</span>'; // Failure message
// Start processing data
latVal = lat.val();
lngVal = lng.val();
if (latVal == '') {
latVal = defaultLat;
lngVal = defaultLng;
}
initmap('map_canvas', lat, lng, zoom, 'ROADMAP');
function initmap(mapId, lat, lng, zoomFactor, mapType) {
var options = {
zoom: zoomFactor,
draggable: true,
center: null,
mapTypeId: google.maps.MapTypeId.HYBRID,
scrollwheel: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
},
scaleControl: true
};
if(mapType == 'SATELLITE') options.mapTypeId = google.maps.MapTypeId.SATELLITE;
else if(mapType == 'ROADMAP') options.mapTypeId = google.maps.MapTypeId.ROADMAP;
options.center = new google.maps.LatLng(latVal, lngVal);
var map = new google.maps.Map(document.getElementById(mapId), options);
var userCoords = new google.maps.LatLng(defaultLat, defaultLng),
marker = new google.maps.Marker({
position: options.center,
map: map,
draggable: options.draggable
}),
userMarker = new google.maps.Marker({
position: userCoords,
title: 'Location',
map: map,
visible: false,
draggable: false
}),
postInfo = new google.maps.InfoWindow({
content: infoWindow
}),
circleRadius = 25000, // Unit: meters
circle = new google.maps.Circle({
map: map,
clickable: false,
radius: circleRadius,
fillColor: '#6cf',
fillOpacity: .4,
strokeColor: '#069',
strokeOpacity: .4,
strokeWeight: .8
});
circle.bindTo('center', userMarker, 'position'); // Attach circle to user position
var bounds = circle.getBounds(); // Bounds of the circle
google.maps.event.addListener(marker, 'dragend', function() {
postCoords = new google.maps.LatLng(marker.position.lat(), marker.position.lng());
});
google.maps.event.addListener(marker, 'click', function() {
postInfo.open(map, marker);
});
google.maps.event.addListener(marker, 'dragend', function(event) { // Recalculate coordinates on marker dragging
var geocoder = new google.maps.Geocoder();
var position = this.getPosition();
lat.val(position.lat());
lng.val(position.lng());
geocoder.geocode({ 'latLng': position }, function() {
if(bounds.contains(position)) {
notes.html(messageTrue);
notes.show();
lat.css({'color': 'green'});
lng.css({'color': 'green'});
}
else {
notes.html(messageFalse);
notes.show();
lat.val('Not allowed!');
lng.val('Not allowed!');
lat.css({'color': 'red'});
lng.css({'color': 'red'});
};
});
});
$('#calculate').click(function() {
postAddress = street.val() + ' ' + postcode.val() + ' ' + city.val() + ' ' + region.val() + ' ' + country.val(); // Generate address string from input fields
var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'address': postAddress}, function(results, status) {
if(status == google.maps.GeocoderStatus.OK && results[0]) {
var position = results[0].geometry.location;
map.setCenter(position);
marker.setPosition(position);
lat.val(position.lat());
lng.val(position.lng());
}
if(bounds.contains(position)) {
notes.html(messageTrue);
notes.show();
lat.css({'color': 'green'});
lng.css({'color': 'green'});
}
else {
notes.html(messageFalse);
notes.show();
lat.val('Not allowed!');
lng.val('Not allowed!');
lat.css({'color': 'red'});
lng.css({'color': 'red'});
};
});
return true;
});
};
});
})(jQuery);
</script>
<div><?php echo $cck->renderField('art_title');?></div>
<div><?php echo $cck->renderField('art_type');?></div>
<div><?php echo $cck->renderField('art_map_country');?></div>
<div><?php echo $cck->renderField('art_map_region');?></div>
<div><?php echo $cck->renderField('art_map_city');?></div>
<div><?php echo $cck->renderField('art_map_street');?></div>
<div class="largepaddingbottom"><?php echo $cck->renderField('art_map_zip');?></div>
<div><a id="calculate" class="btn btn-success btn-medium"><?php echo $buttonText; ?></a> <span id="notes" style="display:none;"></span></div>
<div><?php echo $cck->renderField('art_introtext');?></div>
<div><?php echo $cck->renderField('art_tags');?></div>
<div><?php echo $cck->renderField('art_image_fulltext');?></div>
<div><?php echo $cck->renderField('art_image_gallery');?></div>
<div><?php echo $cck->renderField('button_submit');?></div>
This is a screenshot when calculated position is inside the circle:
This is when calculated position is not inside the circle:
In this way I was able to do the validation on lat/lng fields with Seblod built-in alphanumeric plugin: if coords are inside the circle then lat/lng fields are filled with coords (only numbers) calculated with Gmaps API; if coords are not inside the circle then lat/lng fields are filled via JS with the value “Not allowed!” (with the special character ‘!’ at the end); Lat and Lng fields are visible under the map in screenshots and both set read-only.
Now I’m wondering if the validation made in this way can be skipped somehow.