var absoluteURL = '//www.epcdeskundigen.be/';
/**
* @seee http://studiowhiz.com/2010/10/02/google-maps-v3-distancefrom/
* @param {google.maps.LatLng} newLatLng
* @returns {number}
*/
google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
// setup our variables
var lat1 = this.lat();
var radianLat1 = lat1 * ( Math.PI / 180 );
var lng1 = this.lng();
var radianLng1 = lng1 * ( Math.PI / 180 );
var lat2 = newLatLng.lat();
var radianLat2 = lat2 * ( Math.PI / 180 );
var lng2 = newLatLng.lng();
var radianLng2 = lng2 * ( Math.PI / 180 );
// sort out the radius, MILES or KM?
var earth_radius = 6378.1; // (km = 6378.1) OR (miles = 3959) - radius of the earth
// sort our the differences
var diffLat = ( radianLat1 - radianLat2 );
var diffLng = ( radianLng1 - radianLng2 );
// put on a wave (hey the earth is round after all)
var sinLat = Math.sin( diffLat / 2 );
var sinLng = Math.sin( diffLng / 2 );
// maths - borrowed from http://www.opensourceconnections.com/wp-content/uploads/2009/02/clientsidehaversinecalculation.html
var a = Math.pow(sinLat, 2.0) + Math.cos(radianLat1) * Math.cos(radianLat2) * Math.pow(sinLng, 2.0);
// work out the distance
var distance = earth_radius * 2 * Math.asin(Math.min(1, Math.sqrt(a)));
// return the distance
return distance;
}
var translate = {"browser_not_compatible":"Uw browser ondersteunt geen Google Maps","supplier_already_selected":"U heeft deze deskundige al geselecteerd.","three_suppliers_overwrite":"U heeft reeds drie deskundigen geselecteerd, wilt u de derde deskundigen overschrijven?","loading":"Bezig met laden...","no_suppliers_selection":"U heeft geen deskundigen geselecteerd.","less_three_suppliers":"U heeft minder dan 3 deskundigen geselecteerd. Weet u zeker dat u door wilt gaan?","not_found":" is niet gevonden.","loading_error":"Fout tijdens laden...","click_to_delete":"Klik om te verwijderen","delete":"Verwijder","select_for_manager":"Selecteer voor offerte-aanvraag<\/span>","goto_marker":"Ga naar locatie op de kaart"}
var country = {"id":"2","active":"1","name":"Belgie","code":"be","language":"1","siteName":"EPC Deskundigen","domain":"epcdeskundigen.be","coord_lat":"50.805935","coord_lng":"4.432983","zoom_level":"8","cluster_gridSize":"80","cluster_maxZoom":"12","gmaps":"maps.google.be\/maps","gkey":"ABQIAAAAQEVFdvZPE6sLB0y05PKJVBSkRzPXn5XGRrxZoUH-hHt3bSxNoRRy8QZHNJQBwdVShNZSq5pK1oHRHQ","gcode":"be","gtracker":"UA-9547875-1","gverify":"eMgFPWZ7NmLMEcx\/e8Y4Wg3\/UbAVUBWTLfB09sVRaOg="}
/**
* Google Maps Application - Basics
* Author: Maikel Leemans
*/
dojo.provide('GMap.basic');
dojo.declare('GMap.basic', null,
{
container: null, // (id | domnode) of container div for GMap
searchMap: null, // (id | domnode) of container div for address search form
searchAddress: null, // (id | domnode) of input element for address search field
map: null, // google.maps.Map object
mapProjection: null, // google.maps.Map active projection object
country: null, // country center location
countryBound: null, // country bound box
/**
* We have two map modi: top level cluster markers and zoomed-in ajax markers.
* See also reEvalMapState()
*/
markerClusterBatch: null, // batch of all processed markers (in markerCluster)
markerCluster: null, // marker manager, cluster version
markerClusterActive: false, // flag - marker cluster manager is active or inactive
markerClusterPBatch: null, // batch of all processed Premioum markers (seperate display, not in markerCluster)
markerAjaxBatch: null, // batch of all dynamic markers (obtained via ajax request)
markerManager: null, // marker manager (doubles for markerClusterPBatch and markerAjaxBatch)
markerManagerActive: false, // flag - marker (ajax) manager is active or inactive
activeMarker: null, // current active marker
infoWindow: null, // shared info window (at most one open at any time)
activeStep: 0, // (int) active step in the process
labelerManager: null, // manager object for labeler selection
progressBar: null, // ProgressBarControl
statics:
{
geocoder: null, // geocode client object
preloadIcons: [
'./gfx/gmap/markerNormal.png', //0 normal
'./gfx/gmap/markerActive.png', //1 active
'./gfx/gmap/markerVisited.png', //2 visited
'./gfx/gmap/markerNormalShadow.png', //3 shadow
'./gfx/gmap/markerBigNormal.png', //4 big normal
'./gfx/gmap/markerBigActive.png', //5 big active
'./gfx/gmap/markerBigVisited.png', //6 big visited
'./gfx/gmap/markerBigTransparent.png', //7 big shadow
'./gfx/gmap/ajax-loader.gif' //Loading gif
],
preloadImages: new Array(), // Loaded preload icons
defaultIcon: null,
defaultBigIcon: null,
clusterSettings: {
calculator: function(markers, numStyles)
{
var result = MarkerClusterer.CALCULATOR(markers, numStyles);
return dojo.mixin({}, result, {
text: ""
});
},
styles: [
{
url: './gfx/gmap/cluster1.png',
height: 38,
width: 29,
opt_anchor: [0, 0],
opt_textColor: '#000000'
},
{
url: './gfx/gmap/cluster2.png',
height: 46,
width: 41,
opt_anchor: [0, 0],
opt_textColor: '#ffffff'
},
{
url: './gfx/gmap/cluster3.png',
height: 64,
width: 65,
opt_anchor: [0, 0],
opt_textColor: '#ffffff'
}
]
},
zoomTriggerLoading: 12, // starting from this zoom level, we will request markers and disable the clustermanager (set to country.cluster_maxZoom)
managerSettings: {
borderPadding: 25 // padding for manager (markers partly vissible -> map bound + padding)
},
progressBarSettings: {
loadstring: '
'+translate.loading // text for progress bar
},
markerDeactivatePadding: 80 // the distance from the map-border at which markers will automatically be disabled
// fix for auto-move of mapview after ajaxload
},
/**
* Constructor
*/
constructor: function(container, searchMap, searchAddress, extraContainer, interactionContainer)
{
this.container = container; // container element for the google.maps.Map
this.searchMap = searchMap; // container element for address search form
this.searchAddress = searchAddress; // input element for address search field
dojo.addOnLoad( dojo.hitch(this, 'initialize', extraContainer, interactionContainer) );
},
/**
* Initialize the Google Maps
*/
initialize: function(extraContainer, interactionContainer)
{
// prepare elements
this.container = dojo.byId(this.container);
this.searchMap = dojo.byId(this.searchMap);
this.searchAddress = dojo.byId(this.searchAddress);
this.labelerManager = new GMap.labelerManager(this, extraContainer, interactionContainer);
// v3 has no GBrowserIsCompatible(), so replace by warning text
// on init of v3 maps, this warning text will disappear if the maps work
var property = (document.createElement('div').textContent == null) ? 'innerText': 'textContent';
this.container[property] = translate.browser_not_compatible;
// boot map
this.bootMap();
// init after map booted
google.maps.event.addListener(this.map, 'projection_changed', dojo.hitch(this, function()
{
// initialize basic stuff
if (!(this.initStatics() && this.initMap() && this.initProgressBar() && this.initMarkers()))
{
this.container[property] = translate.browser_not_compatible;
//alert(this.browser_not_compatible);
return;
}
// link address search
dojo.query('form', this.searchMap)
.connect('onsubmit', this, 'showAddress');
// initial center
if (this.searchAddress != null && this.searchAddress.value != ''){
this.showAddress();
}
else{
this.centerCountry();
}
// set active step
this.setActiveStep();
}));
},
/**
* Bootstrap map
*/
bootMap: function()
{
// Initialize map object
this.country = new google.maps.LatLng(country.coord_lat, country.coord_lng);
var myOptions = {
zoom: parseInt(country.zoom_level),
center: this.country,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false,
streetViewControl: false,
panControlOptions: {
position: google.maps.ControlPosition.RIGHT_CENTER
},
zoomControlOptions: {
position: google.maps.ControlPosition.RIGHT_CENTER
}
};
this.map = new google.maps.Map(this.container, myOptions);
if (this.map == null || this.map == false || this.map == undefined)
return false;
return true;
},
/**
* Initialize statics
*/
initStatics: function()
{
// Geocoder
if (this.statics.geocoder == null)
{
this.statics.geocoder = new google.maps.Geocoder();
if (this.statics.geocoder == null || this.statics.geocoder == false || this.statics.geocoder == undefined)
return false;
}
// preload static icon images
if (this.statics.preloadImages.length == 0)
{
for (var index = 0; index < this.statics.preloadIcons.length; index++)
{
this.statics.preloadImages.push(new Image);
this.statics.preloadImages[index].src = this.statics.preloadIcons[index];
}
// Set defaults
this.statics.defaultIcon = {
url: this.statics.preloadImages[0].src,
shape: {
type: 'rect',
coords: [0, 0, , 20, 34]
},
_iconIndexOffset: 0,
};
this.statics.defaultBigIcon = {
url: this.statics.preloadImages[4].src,
size: new google.maps.Size(40, 68),
origin: new google.maps.Point(0,0),
anchor: new google.maps.Point(20, 68),
shape: {
type: 'rect',
coords: [0, 0, , 40, 68]
},
_iconIndexOffset: 4
};
}
// clusterSettings
if (this.statics.clusterSettings.gridSize == undefined || this.statics.clusterSettings.gridSize == null)
{
this.statics.clusterSettings = dojo.mixin(this.statics.clusterSettings,
{
gridSize: parseInt(country.cluster_gridSize), // clustering grid size
maxZoom: parseInt(country.cluster_maxZoom), // starting at this zoomLevel, no clusters are made
loaderDiv: this.loaderDiv // loader overlay
});
//console.dir(this.statics.clusterSettings);
// other settings
// starting from this zoom level, we will request markers and disable the clustermanager
this.statics.zoomTriggerLoading = parseInt(country.cluster_maxZoom);
}
return true;
},
/**
* Initialize Google Maps Basics
*/
initMap: function()
{
this.mapProjection = this.map.getProjection();
this.infoWindow = new google.maps.InfoWindow();
// zoom debug
//GEvent.addListener(this.map, "zoomend", function(oldLevel, newLevel) { console.info('oldLevel: ' + oldLevel + ' - newLevel: ' + newLevel); });
// toggle between cluster and ajax markers on each new map state (eg. zoomend for new zoom level or moveend for new coord box)
// note: zoomend als triggers moveend
google.maps.event.addListener(this.map, "idle", dojo.hitch(this, 'reEvalMapState'));
return true;
},
/**
* Initialize Progressbar control
*/
initProgressBar: function()
{
this.progressBar = new progressBar(this.statics.progressBarSettings);
this.map.controls[google.maps.ControlPosition.RIGHT].push(this.progressBar.getDiv());
return true;
},
/**
* Initialize Markers for Map
*/
initMarkers: function()
{
// bound NL prep
this.countryBound = new google.maps.LatLngBounds(this.country, this.country);
// data is declared in the html body
// Iterate data list, create country bound and add all markers
if (typeof(data) == 'undefined')
return false;
this.progressBar.start(data.length);
this.markerClusterBatch = new Array();
this.markerClusterPBatch = new Array();
for (var index = 0; index < data.length; index++)
{
//Get location
data[index]['coord'] = new google.maps.LatLng(data[index]['coordinate'][0], data[index]['coordinate'][1], data[index]['coordinate'][2]);
//Extent bound
this.countryBound.extend(data[index]['coord']);
//Add marker
var marker = this.createMarker(data[index]['coord'], data[index]['id'], index, data[index]['active'], false);
if (data[index]['isPremium'])
{
marker.isPremium = data[index]['isPremium'];
this.markerClusterPBatch.push(marker);
//this.map.addOverlay(marker);
}
else
this.markerClusterBatch.push(marker);
this.progressBar.setCurrent(index);
}
//console.log('markerClusterBatch: ' + this.markerClusterBatch.length);
// add normal marks to the cluster manager
this.enableClusterManager();
this.progressBar.hide();
return true;
},
/**
* Create a marker object
* onclick - db data details
*/
createMarker: function(point, id, index, activeState, isPremium)
{
if (isPremium)
{
var marker = new google.maps.Marker({
position: point,
map: this.map,
icon: dojo.mixin({}, this.statics.defaultBigIcon),
shadow: dojo.mixin({}, this.statics.defaultBigIcon, {
url: this.statics.preloadImages[
3 + this.statics.defaultBigIcon._iconIndexOffset
].src
})
});
}
else
{
var marker = new google.maps.Marker({
position: point,
map: this.map,
icon: dojo.mixin({}, this.statics.defaultIcon),
shadow: dojo.mixin({}, this.statics.defaultIcon, {
url: this.statics.preloadImages[
3 + this.statics.defaultIcon._iconIndexOffset
].src
})
});
}
// click and visited
marker.visited = false;
marker.isPremium = isPremium;
google.maps.event.addDomListener(marker, 'click', dojo.hitch(this, function()
{
// tracker
ga('send', 'pageview', '/clicks/mapMarker/' + id);
// get database data
this.infotabLoad(marker);
dojo.xhrGet({
url: './public/zoeken_getmapdata.php?id=' + id,
handleAs: 'json',
timeout: 5000, // in miliseconds
load: dojo.hitch(this, 'infotabComplete', marker, index),
error: dojo.hitch(this, 'infotabError', marker)
});
// set previous to visited
if (this.activeMarker != null)
this.setMarkerVisited(this.activeMarker);
// set icon to active
this.setMarkerActive(marker);
this.activeMarker = marker;
marker.visited = true;
}));
return marker;
},
/**
* Change icon of marker to active
*/
setMarkerActive: function(marker)
{
var icon = marker.getIcon();
icon.url = this.statics.preloadImages[1 + icon._iconIndexOffset].src;
marker.setIcon(icon);
},
/**
* Change icon of marker to visited
*/
setMarkerVisited: function(marker)
{
var icon = marker.getIcon();
icon.url = this.statics.preloadImages[2 + icon._iconIndexOffset].src;
marker.setIcon(icon);
this.infoWindow.close();
},
/**
* Make the current active marker inactive
*/
setActiveMarkerVisited: function()
{
if (this.activeMarker != null)
{
//console.info('setActiveMarkerVisited');
this.setMarkerVisited(this.activeMarker);
this.activeMarker = null;
}
},
/**
* info tab xhr event handlers (createMarker -> click -> zoeken_getmapdata.php?id=)
*/
infotabLoad: function(marker)
{
this.markerSetInfoWindow(marker, translate.loading);
},
infotabError: function(marker)
{
this.markerSetInfoWindow(marker, translate.loading_error);
},
infotabComplete: function(marker, markerIndex, response)
{
if (response._error)
this.markerSetInfoWindow(marker, response._msg);
else
this.markerSetInfoWindow(marker, this.formatData(dojo.mixin(response, {markerIndex: markerIndex})));
},
/**
* Open an info window balloon for a marker
*/
markerSetInfoWindow: function(marker, content)
{
this.infoWindow.setContent(content);
this.infoWindow.open(this.map, marker);
},
/**
* trigger onclick for marker, displaying its info box, etc.
*/
activateMarkerByIndex: function(index, event)
{
if (event)
event.preventDefault();
console.warn('activateMarkerByIndex() - code disabled');
//GEvent.trigger(this.markerClusterBatch[index], 'click');
},
/**
* Activate given marker
*/
activateMarkerByRef: function(marker)
{
google.maps.event.trigger(marker, 'click');
},
/**
* Center on country
*/
centerCountry: function()
{
// zoom accoarding to the bound
var zoom = this.getZoomByBounds(this.countryBound);
if (zoom < 8)
zoom = 7;
else if (zoom > 11)
zoom = 11;
//this.map.setCenter(this.countryBound.getCenter(), zoom);
this.map.setCenter(this.countryBound.getCenter());
this.map.setZoom(zoom);
/**
* debug bound
* /
var newBound = this.boundApplyPixelPadding(this.map.getBounds(), this.map.getZoom(), this.statics.managerSettings.borderPadding);
var southWest = newBound.getSouthWest();
var northEast = newBound.getNorthEast();
var polygonData = [
new GLatLng(northEast.lat(), northEast.lng()),
new GLatLng(southWest.lat(), northEast.lng()),
new GLatLng(southWest.lat(), southWest.lng()),
new GLatLng(northEast.lat(), southWest.lng()),
new GLatLng(northEast.lat(), northEast.lng())
];
this.map.addOverlay(new GPolygon(polygonData, "#ff0000", 5, 0.5, "#00ff00", 0.5, []));
//*/
},
/**
* Returns the zoom level at which the given rectangular region fits in the map view.
* The zoom level is computed for the currently selected map type.
* @see http://stackoverflow.com/questions/9837017/equivalent-of-getboundszoomlevel-in-gmaps-api-3
*
* @param {google.maps.Map} map
* @param {google.maps.LatLngBounds} bounds
* @return {Number} zoom level
**/
getZoomByBounds: function(bounds)
{
var MAX_ZOOM = this.map.mapTypes.get( this.map.getMapTypeId() ).maxZoom || 21 ;
var MIN_ZOOM = this.map.mapTypes.get( this.map.getMapTypeId() ).minZoom || 0 ;
var ne= this.mapProjection.fromLatLngToPoint( bounds.getNorthEast() );
var sw= this.mapProjection.fromLatLngToPoint( bounds.getSouthWest() );
var worldCoordWidth = Math.abs(ne.x-sw.x);
var worldCoordHeight = Math.abs(ne.y-sw.y);
//Fit padding in pixels
var FIT_PAD = 40;
for( var zoom = MAX_ZOOM; zoom >= MIN_ZOOM; --zoom ){
var posinfo = dojo.position(this.map.getDiv());
if( worldCoordWidth*(1< 0)
content.addContent(dojo.create('img', {src: 'files/image/' + data.logo, 'class': 'supp_logo', alt: ''}));
// add title / name
if (data.name == '')
content.addContent(dojo.create('b', {innerHTML: data.contact}));
else
content.addContent(dojo.create('b', {innerHTML: data.name}));
// add optional contact
if (data.name != '' && data.contact != '')
content.addContent(dojo.create('br')).addContent(dojo.create('span', {innerHTML: data.contact}));
// add info
content
.addContent(dojo.create('br')).addContent(dojo.create('span', {innerHTML: data.address}))
.addContent(dojo.create('br')).addContent(dojo.create('span', {innerHTML: data.postalcode + ' ' + data.city}))
.addContent(dojo.create('br')).addContent(dojo.create('br'));
// add additional text (for premium-accounts)
if (data.isPremium && data.ad_text != '')
content.addContent(dojo.create('div', {innerHTML: data.ad_text, 'class': 'supp_ad_text'}));
// select for labelManager link
dojo.query(dojo.create('a', {'class': 'selectMgrLink map__button', innerHTML: '« ' + translate.select_for_manager}, content[0]))
.onclick(dojo.hitch(this.labelerManager, 'addLabeler', data));
// return result
return content[0];
},
/**
* Perform geocoding search for address
*/
showAddress: function(event)
{
if (event)
event.preventDefault();
//console.log('begin search');
// var start = new Date();
var geoQuery = {
'address': this.searchAddress.value,
'region': country.gcode
};
// search address by means of the geocoder client
this.statics.geocoder.geocode(geoQuery, dojo.hitch(this, function(results, status)
{
// check point
if (status != google.maps.GeocoderStatus.OK)
{
alert(this.searchAddress.value + ' ' + translate.not_found);
return;
}
var point = results[0].geometry.location;
// update active step to 2
this.setActiveStep(2);
// we want a result in which markers are shown
// to this end, we first find out the closest point to the address
var coord = null;
var distance = null;
for (var index = 0; index < data.length; ++index)
{
if (distance === null)
{
coord = data[index]["coord"];
distance = point.distanceFrom(coord);
}
else if (distance > point.distanceFrom(data[index]["coord"]))
{
coord = data[index]["coord"];
distance = point.distanceFrom(coord);
}
}
// next we create a point mirrored from coord over point
var latlng = {lat: 0, lng: 0};
var coord_mirror = null;
latlng["lat"] = coord.lat() - point.lat();
latlng["lng"] = coord.lng() - point.lng();
latlng["lat"] = point.lat() - latlng["lat"];
latlng["lng"] = point.lng() - latlng["lng"];
coord_mirror = new google.maps.LatLng(latlng["lat"], latlng["lng"]);
// then we create a bound from these points
// first determine the northeast and southwest points
latlng = [{lat: 0, lng: 0}, {lat: 0, lng: 0}];
if (coord.lat() > coord_mirror.lat())
{
latlng[0]["lat"] = coord.lat();
latlng[1]["lat"] = coord_mirror.lat();
}
else
{
latlng[1]["lat"] = coord.lat();
latlng[0]["lat"] = coord_mirror.lat();
}
if (coord.lng() > coord_mirror.lng())
{
latlng[0]["lng"] = coord.lng();
latlng[1]["lng"] = coord_mirror.lng();
}
else
{
latlng[1]["lng"] = coord.lng();
latlng[0]["lng"] = coord_mirror.lng();
}
// finally, create bound ...
var northeast = new google.maps.LatLng(latlng[0]["lat"], latlng[0]["lng"]);
var southwest = new google.maps.LatLng(latlng[1]["lat"], latlng[1]["lng"]);
var bound = new google.maps.LatLngBounds(southwest, northeast);
// ... and zoom accoarding to the bound
var zoom = this.getZoomByBounds(bound);
this.centerCountry();
if (zoom >= 8)
{
if (zoom > 12)
zoom = 12;
//var end = new Date();
//console.log('timing begin search: ' + (end - start));
//console.log('set search');
setTimeout(dojo.hitch(this, function()
{
//var start = new Date();
this.map.setCenter(bound.getCenter());
this.map.setZoom(zoom);
//var end = new Date();
//console.log('timing set search: ' + (end - start));
}), 1);
}
}));
},
/**
* Determines if the given marker may still be active in the new view-bound
*/
evaluateMarkerActiveValidity: function(marker, bound, zoom)
{
var paddedBound = this.boundApplyPixelPadding(bound, zoom, this.statics.markerDeactivatePadding);
return paddedBound.contains( marker.getPosition() );
},
/**
* toggle between cluster and ajax markers on each new map state (eg. zoomend for new zoom level or moveend for new coord box)
*/
reEvalMapState: function()
{
//console.info('currentZoom: ' + this.map.getZoom() + ' currentCoord: ' + this.map.getBounds());
var zoom = this.map.getZoom();
var bound = this.map.getBounds();
// if active marker is not within new result, set it to null
if (this.activeMarker != null)
{
if (!this.evaluateMarkerActiveValidity(this.activeMarker, bound, zoom))
this.setActiveMarkerVisited();
}
if (zoom < 9 && this.markerClusterActive)
this.markerCluster.setGridSize(50);
else if(this.markerClusterActive)
this.markerCluster.setGridSize(this.statics.clusterSettings.gridSize);
if (zoom >= this.statics.zoomTriggerLoading)
{
// ajax markers mode
//console.info('ajax markers mode');
this.disableClusterManager();
this.queryAjaxMarkers(zoom, bound);
}
else
{
// cluster markers mode
//console.info('cluster markers mode');
this.disableAjaxMarkers();
this.enableClusterManager();
}
},
/**
* Disable the influence (event listening) and overlays (markers and clusters) of the markercluster manager
*/
disableClusterManager: function()
{
if (!this.markerClusterActive)
return;
// clear marker cluster batch (MarkerClusterer)
this.markerCluster.clearMarkers();
this.markerCluster = null;
// clear marker premium batch (MarkerManager)
this.markerManager.clearMarkers();
this.markerManager = null;
this.activeMarker = null;
this.markerClusterActive = false;
},
/**
* Enable the influence (event listening) and overlays (markers and clusters) of the markercluster manager
*/
enableClusterManager: function()
{
if (this.markerClusterActive)
return;
// set marker cluster batch (MarkerClusterer)
this.markerCluster = new MarkerClusterer(this.map, this.markerClusterBatch, this.statics.clusterSettings);
// set marker premium batch (MarkerManager)
this.markerManager = new MarkerManager(this.map, this.statics.managerSettings);
google.maps.event.addListener(this.markerManager, 'loaded', dojo.hitch(this, function()
{
this.markerManager.addMarkers(this.markerClusterPBatch, 0);
this.markerManager.refresh();
}));
this.markerClusterActive = true;
},
boundApplyPixelPadding: function(bound, zoom, padding)
{
var southWest = this.fromLatLngToPixel(bound.getSouthWest(), zoom);
southWest.x -= padding;
southWest.y += padding;
southWest = this.fromPixelToLatLng(southWest, zoom);
var northEast = this.fromLatLngToPixel(bound.getNorthEast(), zoom);
northEast.x += padding;
northEast.y -= padding;
northEast = this.fromPixelToLatLng(northEast, zoom);
return new google.maps.LatLngBounds(southWest, northEast);
},
fromLatLngToPixel: function(latlng, zoom)
{
// @see http://qfox.nl/notes/116
var normalizedPoint = this.mapProjection.fromLatLngToPoint(latlng); // returns x,y normalized to 0~255
var scale = Math.pow(2, zoom);
var pixelCoordinate = new google.maps.Point(normalizedPoint.x * scale, normalizedPoint.y * scale);
return pixelCoordinate;
},
fromPixelToLatLng: function(point, zoom)
{
// @see http://qfox.nl/notes/116
var scale = Math.pow(2, zoom);
var normalizedPoint = new google.maps.Point(point.x / scale, point.y / scale);
var latlng = this.mapProjection.fromPointToLatLng(normalizedPoint);
return latlng;
},
/**
* this method actually makes the ajax post request
*/
queryAjaxMarkers: function (zoom, bound)
{
// we initialize the marker manager (note: not the cluster version, but the plain version for ajax markers)
this.enableAjaxMarkers();
this.progressBar.setLoadText(this.statics.progressBarSettings.loadstring);
this.progressBar.start(1);
// manager uses bound padding, so we query with bound padding
var newBound = this.boundApplyPixelPadding(bound, zoom, this.statics.managerSettings.borderPadding);
var southWest = newBound.getSouthWest();
var northEast = newBound.getNorthEast();
bound = [
[southWest.lat(), southWest.lng()],
[northEast.lat(), northEast.lng()]
];
// get database data
dojo.xhrPost({
url: './public/zoeken_getmarkerdata.php?',
content: {"bound": dojo.toJson(bound), "skip": dojo.toJson(this.markerAjaxBatch)},
handleAs: 'json',
timeout: 5000, // in miliseconds
load: dojo.hitch(this, 'processAjaxMarkers'),
error: dojo.hitch(this, 'errorAjaxMarkers')
});
},
/**
* in case of an ajax loading error
*/
errorAjaxMarkers: function()
{
console.error('errorAjaxMarkers');
this.progressBar.setLoadText(translate.loading_error);
this.progressBar.start(1);
},
/**
* in case of a succesful ajax load
*/
processAjaxMarkers: function(data)
{
this.progressBar.start(data.length);
var batch = new Array();
for (var index = 0; index < data.length; index++)
{
//Get location
data[index]['coord'] = new google.maps.LatLng(data[index]['coordinate'][0], data[index]['coordinate'][1], data[index]['coordinate'][2]);
//Add marker
var marker = this.createMarker(data[index]['coord'], data[index]['id'], index, data[index]['active'], data[index]['isPremium']);
this.markerAjaxBatch.push(data[index]['id']);
batch.push(marker);
this.progressBar.setCurrent(index);
}
this.markerManager.addMarkers(batch, this.statics.zoomTriggerLoading);
this.markerManager.refresh();
this.progressBar.hide();
try
{
if (this.activeMarker != null)
this.activateMarkerByRef(this.activeMarker);
}
catch(e)
{
console.error('activateMarkerByRef');
console.dir(e);
}
//console.log('markerAjaxBatch: ' + this.markerAjaxBatch.length);
//console.log('[batch]: ' + batch.length);
},
/**
* turn on the marker manager
*/
enableAjaxMarkers: function()
{
if (this.markerManagerActive)
return;
// prepare marker ajax batch (MarkerManager)
this.markerManager = new MarkerManager(this.map, this.statics.managerSettings);
this.markerAjaxBatch = new Array();
this.markerManagerActive = true;
},
/**
* turn off the marker manager and free resources
*/
disableAjaxMarkers: function()
{
if (!this.markerManagerActive)
return;
// clear marker ajax batch (MarkerManager)
this.markerManager.clearMarkers();
this.markerManager = null;
this.markerAjaxBatch = null;
this.activeMarker = null;
this.markerManagerActive = false;
},
/**
* set te active step in the process
*/
setActiveStep: function(step)
{
var newStep = 0;
if (step == undefined) {
if (this.searchAddress.value != '') {
newStep = 2;
} else {
newStep = 1;
}
} else if (step > -1 && step < 4) {
newStep = step;
}
if (newStep != this.activeStep) {
// Reset step styling
dojo.removeClass("search_map", "route__step--active");
dojo.removeClass("gmap_interaction_step", "route__step--active");
if (newStep == 1) {
// set step 1 styling (search block active)
dojo.addClass("search_map", "route__step--active");
}
else if (newStep == 2) {
// set step 2 styling (select block active)
dojo.addClass("gmap_interaction_step", "route__step--active");
}
this.activeStep = newStep;
}
}
});
/**
* Google Maps Application - Labelers selection and managing
* Author: Maikel Leemans
*/
dojo.provide('GMap.labelerManager');
dojo.declare('GMap.labelerManager', null,
{
mapObject: null, // reference to the parenting GMap.basic instance
labelerArray: null, // array with last selected labelers
labelerLimit: 3, // limited size of labelerArray
extraContainer: null, // div for extra info (labelers list)
interactionContainer: null, // div for labelers list interaction
labelerList: null, // DOM reference for laberlers list display container
/**
* Constructor
*/
constructor: function(mapObject, extraContainer, interactionContainer)
{
this.labelerArray = new Array();
this.mapObject = mapObject;
this.extraContainer = dojo.byId(extraContainer);
this.interactionContainer = dojo.byId(interactionContainer);
this.labelerList = false; // created when needed in updateLabelerList()
// connect interaction
dojo.query('a', this.interactionContainer)
.connect('onclick', dojo.hitch(this, 'sendLeads'));
},
/**
* Add a new labeler to the array
* Manage duplicates and array size
*/
addLabeler: function(data, event)
{
if (event)
event.preventDefault();
// is this labeler already selected => return and alert
for (var i = 0; i < this.labelerArray.length; ++i)
{
if (this.labelerArray[i] == null || this.labelerArray[i] == undefined)
continue;
else if (this.labelerArray[i].id == data.id)
{
alert(translate.supplier_already_selected);
return;
}
}
// check length
if (
this.labelerArray.length >= this.labelerLimit
&& !confirm(translate.three_suppliers_overwrite)
)
return;
// add to beginning of array
this.labelerArray.unshift(data);
// manage array length
while (this.labelerArray.length > this.labelerLimit)
this.labelerArray.pop();
// update page
this.updateLabelerList();
},
removeLabelerByIndex: function(index, event)
{
if (event)
event.preventDefault();
// remove labeler
this.labelerArray.splice(index, 1);
// update page
this.updateLabelerList();
},
/**
* Update the list on the left (map_extra)
* Displaying new labelers selected and request button
*/
updateLabelerList: function()
{
// first time => create list
if (!this.labelerList)
{
dojo.query(this.extraContainer).empty();
this.labelerList = dojo.query(dojo.create('ul', null, this.extraContainer));
// dojo.create('br', {'class': 'clear'}, this.interactionContainer);
}
// first, clear list
this.labelerList.empty();
// (de-)activate the button
if (this.labelerArray.length > 0) {
// activate button
dojo.removeClass("route_button", "not-active");
dojo.removeClass("route_button_sec", "not-active");
} else {
// deactivate button
dojo.addClass("route_button", "not-active");
dojo.addClass("route_button_sec", "not-active");
}
// handle empty list
if (this.labelerArray.length == 0)
{
//dojo.create('span', {innerHTML: translate.no_suppliers_selection}, this.labelerList[0]);
//dojo.attr(this.interactionContainer, { style: {display: 'none'} });
return;
}
// redo list creation
for (var i = 0; i < this.labelerArray.length; ++i)
{
if (this.labelerArray[i] == null || this.labelerArray[i] == undefined)
continue;
// add list item
dojo.query(dojo.create('li', null, this.labelerList[0]))
.addContent(this.formatData(this.labelerArray[i], i));
}
// and, of course, our interaction div is displayed
dojo.attr(this.interactionContainer, { style: {display: 'block'} });
},
/**
* format content for labeler marker list item
*/
formatData: function(data, index)
{
var content = dojo.create('span', {class: 'selected'});
var title = '';
// determine title / name
if (data.name == '')
title = data.contact;
else
title = data.name;
/*
// create link with title
dojo.query(dojo.create('a', {href: '#', title: translate.goto_marker, innerHTML: title}, content))
.connect('onclick', dojo.hitch(this.mapObject, 'activateMarkerByIndex', data.markerIndex));
/*/
dojo.create('span', {title: translate.goto_marker, class: 'selected__name', innerHTML: title}, content);
//*/
// add delete button
dojo.query(dojo.create('a', {'class': 'pointer selected__remove', title: translate.click_to_delete}, content))
.connect('onclick', dojo.hitch(this, 'removeLabelerByIndex', index))
.addContent(dojo.create('img', {src: './public/gfx/theme/cross.svg', 'class': 'icon', alt: translate['delete']}));
// add hidden field for labelersform
dojo.create('input', {type: 'hidden', name: 'menu_extra' + index, value: data.id}, content);
// return result
return content;
},
sendLeads: function (event)
{
if (event)
event.preventDefault();
if (this.labelerArray.length == 0)
{
alert(translate.no_suppliers_selection);
return;
}
/*
else if (
this.labelerArray.length < this.labelerLimit
&& !confirm(translate.less_three_suppliers))
return;
*/
dojo.byId('labelersform').submit();
}
});
var gmap = new GMap.basic(
'gmap_main', /* DOM id - div for Gmap (actual map) */
'search_map', /* DOM id - div with address search form */
'address_input', /* DOM id - input element for address search field */
'gmap_extra', /* DOM id - div for extra info (labelers list) */
'gmap_interaction' /* DOM id - div for labelers list interaction */
);