function Job(job, _category) { var base = this; this.category = _category; this.street = job.street; this.suburb = job.suburb; this.type = job.type; this.status = job.status; this.lat = parseFloat(job.lat); this.lng = parseFloat(job.lng); this.created_at = job.created_at; this.updated_at = job.updated_at; this.ended_at = job.ended_at; this.source = job.source; this.reference = job.wo; this.description = job.description; } function MapMarker(jobs){ var base = this; var map = FaultMap.getInstance(); var firstJob = jobs[0] this.jobs = jobs this.lat = firstJob.lat; this.lng = firstJob.lng; this.street = firstJob.street; this.suburb = firstJob.suburb; // If theres a fault on this point, make it a fault icon, otherwise work. this.markerCategory = jobs.filter(function(j){ return j.category == 'fault' }).length > 0 ? 'fault' : 'work'; var m = new google.maps.Marker({ position: { lat: this.lat, lng: this.lng }, icon: map.MAP_URL + '/'+this.markerCategory+'.png', clickable: true }); m.addListener('click', function(){ map.renderDetails(base); }); this.googleMarker = m; // add map button to lists var mapLink = document.createElement('a'); $(mapLink) .addClass('show-on-map btn form-control') .attr('href',"#map-legend") .attr('data-details',this.category + ': ' + this.street + ', '+this.suburb+': '+this.lat+','+this.lng) .text('View on Map'); var $listEntry = $('.works_indent > div > div > div') $listEntry = $listEntry.has('.inter-address:contains("'+this.suburb+'")') .has('.inter-address:contains("'+ this.street +'")') .find('.inter-text'); if( $listEntry.find('.show-on-map').length == 0 && $listEntry.length > 0 && !(typeof(base.lat) === 'number' && isNaN(base.lat)) ){ $listEntry.each(function(ind,el){ var $linkClone = $(mapLink).clone() $linkClone.insertBefore($(el).find('.inter-body')); $linkClone.after('
'); $linkClone.on('click', function(){ google.maps.event.addListenerOnce(map.gMap, 'idle', function(){ google.maps.event.trigger(base.googleMarker, 'click'); }); map.gMap.setZoom(14); map.gMap.setCenter(base.googleMarker.getPosition()); }); }) } } var FaultMap = (function(){ // setup Singleton Use var INSTANCE; function FaultMap(initVars) { if (!(this instanceof FaultMap)) { return new FaultMap(initVars); } this.selector = initVars.selector; this.scheduledWorks = initVars.scheduledWorks; this.majorFaults = initVars.majorFaults; this.MAP_URL = '/major-faults-and-scheduled-works-map' // markers. and jobs this.markers = []; this.jobs = []; this.majorFaultJobs = []; this.scheduledWorkJobs = []; // google variable storage this.gMap = null; this.gMarkerCluster = null; this.infoWindow = null; this.searchBounds = null; this.addressAutocomplete = null; this.activeAddress = null; } FaultMap.prototype.createJob = function(job, type) { if (job.lat != '' && job.lng != ''){ var job = new Job(job, type); this.jobs.push(job); return job; } }; FaultMap.prototype.createMarker = function(job, type) { if (job.lat != '' && job.lng != ''){ var marker = new MapMarker(job, type); this.markers.push(marker); return marker; } }; FaultMap.prototype.mapInit = function(){ var base = this; this.gMap = new google.maps.Map(document.getElementById(this.selector), { zoom: 10, center: {lat: -34.928744, lng: 138.599532}, styles: [{"featureType": "poi.business","stylers": [{"visibility": "off"}]},{"featureType": "road","elementType": "labels.icon","stylers": [{"visibility": "off"}]},{"featureType": "transit","stylers": [{"visibility": "off"}]}], fullscreenControl: false, mapTypeControl: false, streetViewControl: false, fullscreenControl: false }); // setup info window this.infoWindow = new google.maps.InfoWindow({ content: '', zIndex: 200 }); // setup Jobs this.majorFaultJobs = this.majorFaults.map(function(job) { var j = base.createJob(job, 'fault'); return j; }); this.scheduledWorkJobs = this.scheduledWorks.map(function(job) { var j = base.createJob(job, 'work'); return j; }); // setup markers this.jobs = Object.values(_.groupBy(this.jobs, function(j){ return (j.lat + '-' + j.lng) })) this.jobs.map(function(jobGroup){ base.createMarker(jobGroup) }) // Add a marker clusterer to manage the markers. this.gMarkerCluster = new MarkerClusterer(this.gMap, this.markers.map(function(marker){ return marker.googleMarker; }), { imagePath: this.MAP_URL+'/m' }); // setup Report a Fault button var $reportBtn = $('#report-a-fault-btn').detach(); this.gMap.controls[google.maps.ControlPosition.LEFT_BOTTOM].push($reportBtn[0]) // setup Address search var boundSA = new google.maps.LatLngBounds( // bound address search to south australia new google.maps.LatLng(-38.0676908,128.992791), new google.maps.LatLng(-25.9955172,140.998021) ); this.addressAutocomplete = new google.maps.places.Autocomplete(document.getElementById('address-search'), { bounds: boundSA, strictBounds: true, types: ["geocode"] }); this.addressAutocomplete.addListener('place_changed', this.findCloseJobs); this.activeAddress = new google.maps.Marker({ map: this.gMap }); navigator.geolocation.getCurrentPosition(function(location) { base.setLocalMarker({ lat: location.coords.latitude, lng: location.coords.longitude }); }); $('.use-current-location').on('click', function(){ navigator.geolocation.getCurrentPosition(function(location) { base.setLocalMarker({ lat: location.coords.latitude, lng: location.coords.longitude }); }); }); }; FaultMap.prototype.renderDetails = function(marker) { var base = this $panelHtml = "" marker.jobs.forEach(function(job){ var $panel = $(job.category == 'work' ? '#work-info-wrapper' : '#fault-info-wrapper'); $panel = base.preparePanel($panel.clone(), job); $panelHtml += $panel.html(); }) this.infoWindow.setContent($panelHtml); this.infoWindow.open(this.gMap, marker.googleMarker); //this.infoWindow.setContent(this.infoWindow.getContent()); }; FaultMap.prototype.preparePanel = function($panel, job){ $panel.find('.work-address').text(job.street + ', ' + job.suburb); $panel.find('.work-description').html(job.description); if( job.reference ){ $panel.find('.work-details .reference span').text(job.reference); $panel.find('.work-details .reference').show(); }else{ $panel.find('.work-details .reference').hide(); } $panel.find('.work-details .status .job-status').text(job.status); $panel.find('.work-details .status .job-status').addClass(job.status.toLowerCase()); if(job.type != ''){ $panel.find('.work-type').text(job.type); } $panel.find('.work-details .water-on span').text(job.ended_at); $panel.find('.work-details .updated span').text(job.updated_at); $panel.find('.job-info').addClass('info-window-panel') return $panel; }; FaultMap.prototype.renderLocalJobs = function(marker) { var base = this $panelHtml = "" marker.jobs.forEach(function(job){ var $panel = $(job.category == 'work' ? '#work-info-wrapper' : '#fault-info-wrapper'); $panel = base.preparePanel($panel.clone(), job); $panelHtml += $panel.html(); }) $('#job-listings').append($panelHtml); $('#job-listings').show(); }; FaultMap.prototype.emptyLocalJobs = function(){ $('#job-listings').html(''); $('#job-listings').hide(); }; FaultMap.prototype.findCloseJobs = function() { var place = this.getPlace(); var location = place.geometry.location; INSTANCE.infoWindow.close(); INSTANCE.setLocalMarker(location); }; FaultMap.prototype.setLocalMarker = function(location) { var noNearbyWorks = true; INSTANCE.emptyLocalJobs(); INSTANCE.activeAddress.setPosition(location); INSTANCE.gMap.setCenter(location); if(window.screen.width < 768){ INSTANCE.gMap.setZoom(14); }else{ INSTANCE.gMap.setZoom(15); } INSTANCE.markers.forEach(function(marker){ if(INSTANCE.gMap.getBounds().contains(marker.googleMarker.position)){ noNearbyWorks = false; INSTANCE.renderLocalJobs(marker); } }); if ( noNearbyWorks ){ $('#no-works').show(); }else{ $('#no-works').hide(); } }; return { init: function() { if (!INSTANCE) { INSTANCE = FaultMap.apply(null, arguments); return INSTANCE; } return INSTANCE; }, getInstance: function() { if (!INSTANCE) { return this.init.apply(this, arguments); } return INSTANCE; } }; }());