/**
* @author Yaron Koren
*/
/* global L */
function setupMapFormInput( inputDiv, mapService ) {
var map, marker, markers, mapCanvas, mapOptions;
var numClicks = 0, timer = null;
if ( mapService === "Google Maps" ) {
mapCanvas = inputDiv.find('.pfMapCanvas')[0];
mapOptions = {
zoom: 1,
center: new google.maps.LatLng(0,0)
};
map = new google.maps.Map(mapCanvas, mapOptions);
var geocoder = new google.maps.Geocoder();
// Let a click set the marker, while keeping the default
// behavior (zoom and center) for double clicks.
// Code copied from http://stackoverflow.com/a/8417447
google.maps.event.addListener( map, 'click', function( event ) {
timer = setTimeout( function() {
googleMapsSetMarker( event.latLng );
}, 200 );
});
google.maps.event.addListener( map, 'dblclick', function( event ) {
clearTimeout( timer );
});
} else if (mapService === "Leaflet") {
mapCanvas = inputDiv.find('.pfMapCanvas').get(0);
mapOptions = {
zoom: 1,
center: [0, 0]
};
var layerOptions = {
attribution: '© OpenStreetMap contributors'
};
map = L.map(mapCanvas, mapOptions);
new L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', layerOptions).addTo(map);
map.on( 'click', function( event ) {
// Place/move the marker only on a single click, not a
// double click (double clicks do a zoom).
// Code based on https://stackoverflow.com/a/7845282
numClicks++;
if (numClicks === 1) {
timer = setTimeout( function() {
leafletSetMarker( event.latlng );
numClicks = 0;
});
} else {
clearTimeout(timer);
numClicks = 0;
}
});
} else { // if ( mapService === "OpenLayers" ) {
var mapCanvasID = inputDiv.find('.pfMapCanvas').attr('id');
map = new OpenLayers.Map( mapCanvasID );
map.addLayer( new OpenLayers.Layer.OSM() );
map.zoomTo(0);
markers = new OpenLayers.Layer.Markers( "Markers" );
map.addLayer( markers );
map.events.register("click", map, function(e) {
numClicks++;
if (numClicks === 1) {
timer = setTimeout( function() {
var opx = map.getLayerPxFromViewPortPx(e.xy) ;
var loc = map.getLonLatFromPixel( opx );
openLayersSetMarker( loc );
numClicks = 0;
});
} else {
clearTimeout(timer);
numClicks = 0;
}
});
}
var coordsInput = inputDiv.find('.pfCoordsInput');
coordsInput.keypress( function( e ) {
// Is this still necessary for IE compatibility?
var keycode = (e.keyCode ? e.keyCode : e.which);
if ( keycode == 13 ) {
setMarkerFromCoordinates();
// Prevent the form from getting submitted.
e.preventDefault();
$(this).removeClass( 'modifiedInput' )
.parent().find('.pfCoordsInputHelpers').remove();
}
});
coordsInput.keydown( function( e ) {
if ( ! coordsInput.hasClass( 'modifiedInput' ) ) {
coordsInput.addClass( 'modifiedInput' );
var checkMark = $('').addClass( 'pfCoordsCheckMark' ).css( 'color', 'green' ).html( '✔' );
var xMark = $('').addClass( 'pfCoordsX' ).css( 'color', 'red' ).html( '✘' );
var marksDiv = $('').addClass( 'pfCoordsInputHelpers' )
.append( checkMark ).append( ' ' ).append( xMark );
coordsInput.parent().append( marksDiv );
checkMark.click( function() {
setMarkerFromCoordinates();
coordsInput.removeClass( 'modifiedInput' );
marksDiv.remove();
});
xMark.click( function() {
coordsInput.removeClass( 'modifiedInput' )
.val( coordsInput.attr('data-original-value') );
marksDiv.remove();
});
}
});
inputDiv.find('.pfAddressInput').keypress( function( e ) {
// Is this still necessary fro IE compatibility?
var keycode = (e.keyCode ? e.keyCode : e.which);
if ( keycode == 13 ) {
setMarkerFromAddress();
// Prevent the form from getting submitted.
e.preventDefault();
}
});
inputDiv.find('.pfLookUpAddress').click( function() {
setMarkerFromAddress();
});
if ( coordsInput.val() != '' ) {
setMarkerFromCoordinates();
map.setZoom( 14 );
} else {
if ( coordsInput.attr('data-bound-coords') ) {
var boundCoords = coordsInput.attr('data-bound-coords');
var coords = boundCoords.split(";");
var boundCoords1 = coords[0];
var lat1 = boundCoords1.split(",")[0].trim();
var lon1 = boundCoords1.split(",")[1].trim();
var boundCoords2 = coords[1];
var lat2 = boundCoords2.split(",")[0].trim();
var lon2 = boundCoords2.split(",")[1].trim();
if ( !jQuery.isNumeric( lat1 ) || !jQuery.isNumeric( lon1 ) ||
!jQuery.isNumeric( lat2 ) || !jQuery.isNumeric( lon2 ) ) {
return;
}
if ( lat1 < -90 || lat1 > 90 || lon1 < -180 || lon1 > 180 ||
lat2 < -90 || lat2 > 90 || lon2 < -180 || lon2 > 180 ) {
return;
}
var bound1 = new google.maps.LatLng(lat1, lon1);
var bound2 = new google.maps.LatLng(lat2, lon2);
var bounds = new google.maps.LatLngBounds();
bounds.extend(bound1);
bounds.extend(bound2);
map.fitBounds(bounds);
}
}
function setMarkerFromAddress() {
var currentMapName = coordsInput.attr('name');
var allFeedersForCurrentMap = jQuery('[data-feeds-to-map="' + currentMapName + '"]').map( function() {
return $( this ).val()
}).get();
if ( allFeedersForCurrentMap.length > 0 ) {
// Assemble a single string from all the address inputs that feed to this map.
var addressText = allFeedersForCurrentMap.join( ', ' );
} else {
// No other inputs feed to this map, so use the standard "Enter address here" input.
var addressText = inputDiv.find('.pfAddressInput').val();
}
if ( mapService === "Google Maps" ) {
geocoder.geocode( { 'address': addressText }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
googleMapsSetMarker( results[0].geometry.location );
map.setZoom(14);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
//} else { // Leaflet, OpenLayers
// Do nothing, for now - address lookup/geocode is
// not yet enabled for Leaflet or OpenLayers.
}
}
function setMarkerFromCoordinates() {
var coordsText = coordsInput.val();
var coordsParts = coordsText.split(",");
if ( coordsParts.length != 2 ) {
coordsInput.val('');
return;
}
var lat = coordsParts[0].trim();
var lon = coordsParts[1].trim();
if ( !jQuery.isNumeric( lat ) || !jQuery.isNumeric( lon ) ) {
coordsInput.val('');
return;
}
if ( lat < -90 || lat > 90 || lon < -180 || lon > 180 ) {
coordsInput.val('');
return;
}
if ( mapService === "Google Maps" ) {
var gmPoint = new google.maps.LatLng( lat, lon );
googleMapsSetMarker( gmPoint );
map.setCenter( gmPoint );
} else if ( mapService === "Leaflet" ){
var lPoint = L.latLng( lat, lon );
leafletSetMarker( lPoint );
map.setView( lPoint, 14 );
} else { // if ( mapService === "OpenLayers" ) {
var olPoint = toOpenLayersLonLat( map, lat, lon );
openLayersSetMarker( olPoint );
map.setCenter( olPoint );
}
}
function toOpenLayersLonLat( map, lat, lon ) {
return new OpenLayers.LonLat( lon, lat ).transform(
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984
map.getProjectionObject() // to Spherical Mercator Projection
);
}
/**
* Round off a number to five decimal places - that's the most
* we need for coordinates, one would think.
*/
function pfRoundOffDecimal( num ) {
return Math.round( num * 100000 ) / 100000;
}
function googleMapsSetMarker(location) {
if (marker == undefined){
marker = new google.maps.Marker({
position: location,
map: map,
draggable: true
});
google.maps.event.addListener( marker, 'dragend', function( event ) {
googleMapsSetMarker( event.latLng );
});
} else {
marker.setPosition(location);
}
var stringVal = pfRoundOffDecimal( location.lat() ) + ', ' + pfRoundOffDecimal( location.lng() );
coordsInput.val( stringVal )
.attr( 'data-original-value', stringVal )
.removeClass( 'modifiedInput' )
.parent().find('.pfCoordsInputHelpers').remove();
}
function leafletSetMarker( location ) {
if ( marker == null) {
marker = L.marker( location ).addTo( map );
} else {
marker.setLatLng( location, { draggable: true } );
}
marker.dragging.enable();
function setInput() {
var stringVal = pfRoundOffDecimal( marker.getLatLng().lat ) + ', ' +
pfRoundOffDecimal( marker.getLatLng().lng );
coordsInput.val( stringVal )
.attr( 'data-original-value', stringVal )
.removeClass( 'modifiedInput' )
.parent().find('.pfCoordsInputHelpers').remove();
}
marker.off('dragend').on('dragend', function( event ) {
setInput();
});
setInput();
}
function openLayersSetMarker( location ) {
// OpenLayers does not have a real marker move
// option - instead, just delete the old marker
// and add a new one.
markers.clearMarkers();
marker = new OpenLayers.Marker( location );
markers.addMarker( marker );
// Transform the coordinates back, in order to display them.
var realLonLat = location.clone();
realLonLat.transform(
map.getProjectionObject(), // transform from Spherical Mercator Projection
new OpenLayers.Projection("EPSG:4326") // to WGS 1984
);
var stringVal = pfRoundOffDecimal( realLonLat.lat ) + ', ' + pfRoundOffDecimal( realLonLat.lon );
coordsInput.val( stringVal )
.attr( 'data-original-value', stringVal )
.removeClass( 'modifiedInput' )
.parent().find('.pfCoordsInputHelpers').remove();
}
}
jQuery(document).ready( function() {
jQuery(".pfGoogleMapsInput").each( function() {
setupMapFormInput( jQuery(this), "Google Maps" );
});
jQuery(".pfLeafletInput").each( function() {
setupMapFormInput( jQuery(this), "Leaflet" );
});
jQuery(".pfOpenLayersInput").each( function() {
setupMapFormInput( jQuery(this), "OpenLayers" );
});
});