/* Google Service Account info */ var clientId = "322504400471-ou3nftefgmhpnbj4v3nv08b16nepdngg.apps.googleusercontent.com"; var apiKey = "AIzaSyA0qZMLnj11C0CFSo-xo6LwqsNB_hKwRbM"; // Access Google Cloud Storage var defaultBucket = "h2o-flint.appspot.com"; var scopes = "https://www.googleapis.com/auth/devstorage.read_only https://www.googleapis.com/auth/fusiontables.readonly"; var windowWidth = window.innerWidth; var windowHeight = window.innerHeight; var $pageId = $("body").attr("id").slice(0, $("body").attr("id").indexOf("_")); var folderPrefix; var map; var mapCenter = {lat: 43.021, lng: -83.681}; var zoomLvl; var geocoder; var autocomplete; var infoWindow; var heatmap; var fusionTableAllId = "17nXjYNo-XHrHiJm9oohgxBSyIXsYeXqlnVHnVrrX"; var leadLayer; // fusion table layer to set up lead levels var leadLayerBirdViewMarkers = []; var leadAndPredictiveLayer; // fusion table layer to show both lead and prediction layer var heatmapData; var $locationButtons; var savedMarkers = []; var allMarkers = []; var allMarkersString = []; var resourceActiveArray = [1, 0, 0, 0, 0, 0, 0, 0]; // lead levels, water pickup, recycle, filter, lead, blood, construction, prediction var oldResourceActiveArray; // the saved resource array that's stored when the user visits the "test my water" or "report" pages var savedLocationMarkers = []; var constructionMarkers = []; var locationMarker; var clickedMarker; var markerImg; var savedLocationTotal; var savedIcon; var resourceMarker; // for construction var constructionMarker; var pipeToggle = 0; // for water plant var waterplantMarker; // for pipe visualization var arrayOfLines = new Array(); var masterPipeArray = new Array(); var autoPolyLine; // icons var bloodIcon; var waterPickupIcon; var leadTestIcon; var recycleIcon; var filterIcon; var pipesIcon; var constructionIcon; var waterPlantIcon; var locationIcon; var savedResourceIcon; var savedLocationIcon; var iconSize = 30; /* The admin site uses the same map.js so the folder depth has to be compensated for. */ if (location.href.indexOf("admin") != '-1') folderPrefix = "../"; else folderPrefix = ""; /* Meters for predicted risk. */ var unknownRiskSrc = folderPrefix+"images/unknownbar.png"; var lowRiskSrc = folderPrefix+"images/lowbar.png"; var moderateRiskSrc = folderPrefix+"images/moderatebar.png"; var highRiskSrc = folderPrefix+"images/highbar.png"; /* Circles for lead data. */ var unknownRiskCircle = folderPrefix+"images/unknownrisklevel.png"; var lowRiskCircle = folderPrefix+"images/lowrisklevel.png"; var medRiskCircle = folderPrefix+"images/medrisklevel.png"; var highRiskCircle = folderPrefix+"images/highrisklevel.png"; var leadLevelOfInput; /* Stores fusion table query callbacks. */ window.jsonpCallbacks = {}; function setAPIKey() { /*if (location.href.indexOf("admin") != '-1') { $('#map_container').parent().prepend('
The map is temporarily unavailable. Please see the resident map at http://www.mywater-flint.com.
'); $('#map_container, #map_layer_selection, #resource_layer_selection').hide(); }*/ //else { gapi.client.setApiKey(apiKey); gapi.load("client:auth2", checkAuth); //} } function checkAuth() { gapi.auth2.init({ client_id: clientId, scope: scopes }).then(function(resp) { initMap(); }); } function initMap() { $("#resource_card, #location_card, #legend_card").hide(); /* Add position:relative; to the map container if not using a mobile device. */ if (windowHeight > 600) { $("wrapper").css("position", "static"); $("#map_container").css("position", "relative"); } /* Size the map based on the window size. */ var mapHeight; if (windowHeight < 600 && windowWidth < 1280) mapHeight = windowHeight - $("#header").outerHeight() - $("#toggles").outerHeight() - $("#legend_card").outerHeight(); else mapHeight = windowHeight - $("#header").outerHeight() - $("#toggles").outerHeight() - $("footer").outerHeight(); $("#map_container").css("height", mapHeight + "px"); map = new google.maps.Map(document.getElementById('map'), { center: mapCenter, zoom: 13, streetViewControl: false, mapTypeControl: false, fullscreenControl: false, gestureHandling: "greedy" }); //This hides all Points of Interest on the map var noPoi = [{ featureType: "poi.attraction", stylers: [{visibility: "off"}] }, { featureType: "poi.business", stylers: [{visibility: "off"}] }, { featureType: "poi.government", stylers: [{visibility: "off"}] }, { featureType: "poi.medical", stylers: [{visibility: "off"}] }, { featureType: "poi.park", stylers: [{visibility: "off"}] }, { featureType: "poi.place_of_worship", stylers: [{visibility: "off"}] }, { featureType: "poi.school", stylers: [{visibility: "off"}] }, { featureType: "poi.sports_complex", stylers: [{visibility: "off"}] }, { featureType: "transit.station", stylers: [{visibility: "off"}] }]; map.setOptions({styles: noPoi}); attachLegendCard(); /* Position the map in the correct element if it exists on the page. */ if($("#search_input").length != 0) $("#map_container #search_input").after($("#map")); $("#search_input").val(""); // clear the search input upon refresh geocoder = new google.maps.Geocoder(); /* Centering and resizing */ google.maps.event.addDomListener(window, "resize", function() { google.maps.event.trigger(map, "resize"); map.setCenter(mapCenter); $("#map").css({ "height": function() { window.innerHeight - $("header").outerHeight() - $("#toggles .list").outerHeight(); } }); }); infoWindow = new google.maps.InfoWindow(); allMarkers.forEach(function(marker) { marker.setMap(null); }); // make icons for each resource bloodIcon = { url: folderPrefix+"images/bloodtest_circle_icon.png", origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 0), size: new google.maps.Size(64, 64), scaledSize: new google.maps.Size(iconSize, iconSize) }; helpCenterIcon = { url: folderPrefix+"images/help_center_circle_icon.png", origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 0), size: new google.maps.Size(64, 64), scaledSize: new google.maps.Size(iconSize, iconSize) }; waterPickupIcon = { url: folderPrefix+"images/water_pickup_circle_icon.png", origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 0), size: new google.maps.Size(64, 64), scaledSize: new google.maps.Size(iconSize, iconSize) }; leadTestIcon = { url: folderPrefix+"images/lead_test_circle_icon.png", origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 0), size: new google.maps.Size(64, 64), scaledSize: new google.maps.Size(iconSize, iconSize) }; recycleIcon = { url: folderPrefix+"images/recycle_circle_icon.png", origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 0), size: new google.maps.Size(64, 64), scaledSize: new google.maps.Size(iconSize, iconSize) }; filterIcon = { url: folderPrefix+"images/water_filter_circle_icon.png", origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 0), size: new google.maps.Size(64, 64), scaledSize: new google.maps.Size(iconSize, iconSize) }; pipesIcon = { url: folderPrefix+"images/pipes_icon.png", origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 0), size: new google.maps.Size(64, 64), scaledSize: new google.maps.Size(iconSize, iconSize) }; constructionIcon = { url: folderPrefix+"images/construction_icon.png", origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 0), size: new google.maps.Size(64, 64), scaledSize: new google.maps.Size(iconSize, iconSize) }; waterplantIcon = { url: folderPrefix+"images/water_plant_icon.png", origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 0), size: new google.maps.Size(64, 64), scaledSize: new google.maps.Size(iconSize, iconSize) }; savedResourceIcon = { url: folderPrefix+"images/saved_resource_icon.png", origin: new google.maps.Point(0,0), anchor: new google.maps.Point(0,0), size: new google.maps.Size(64,64), scaledSize: new google.maps.Size(iconSize, iconSize) }; locationIcon = { url: folderPrefix+"images/location_icon.png", size: new google.maps.Size(64, 64), origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 0), scaledSize: new google.maps.Size(iconSize, iconSize) }; savedLocationIcon = { url: folderPrefix+"images/saved_location_icon.png", origin: new google.maps.Point(0,0), anchor: new google.maps.Point(0,0), size: new google.maps.Size(64,64), scaledSize: new google.maps.Size(iconSize, iconSize) }; /* Only load lead areas on the admin dashboard page. */ if ($pageId.indexOf("dashboard") != -1) { callStorageAPI("leadLevels_birdview.json"); } /* Only load pipe data and construction sites on the index page. */ if ($pageId.indexOf("index") != -1) { callStorageAPI("pipedata.json"); callStorageAPI("construction_sites.json"); } callStorageAPI("providers.json"); setUpFusionTable(); // Create a marker for the place. locationMarker = new google.maps.Marker({map: map}); /* Load saved non-resource locations. */ var numberSaved = parseInt(localStorage["numberSaved"]); if (!isNaN(numberSaved) && (numberSaved > 0)) { for (var i = 1; i <= numberSaved; i++) { var query = "SELECT 'latitude', 'longitude', 'abandoned', 'leadLevel', 'testDate', 'prediction' FROM " + fusionTableAllId + " WHERE address LIKE '" + localStorage.getItem("savedLocationAddress"+i) + "' ORDER BY 'testDate' DESC"; /* Based on code found here: http://stackoverflow.com/questions/21373643/jquery-ajax-calls-in-a-for-loop#21373707 */ (function(index){ window.jsonpCallbacks["fusionQueryCallback"+index] = function(data) { var locationPosition = localStorage.getItem("savedLocationPosition"+index); var latitude = parseFloat(locationPosition.slice(1, locationPosition.indexOf(","))); var longitude = parseFloat(locationPosition.slice(locationPosition.indexOf(" ")+1, locationPosition.indexOf(")"))); var tempLocationMarker = new google.maps.Marker({ position: {lat:latitude, lng:longitude}, map: map, icon: savedLocationIcon }); var streetAddress = localStorage.getItem("savedLocationAddress"+index); var content = fusionQueryCallback(data, streetAddress); attachLocationCard("savedLocation", tempLocationMarker, streetAddress, content); savedMarkers.push(tempLocationMarker); savedLocationMarkers.push(tempLocationMarker); }; })(i); queryFusionTable(query, "jsonpCallbacks.fusionQueryCallback"+i); } } // Water Plant Stuff var waterplantLatLng = {lat:43.056269, lng:-83.669625}; var waterplantTitle = "City of Flint Water Plant"; var waterplantImage = folderPrefix+"images/water_plant_icon.png"; waterplantMarker = new google.maps.Marker({ position : waterplantLatLng, map: map, title: waterplantTitle, icon: waterplantIcon }); var waterplantContent = "4500 N Dort Hwy, Flint, MI 48505
"; bindInfoWindow("waterplant", waterplantMarker, map, infoWindow, waterplantContent); waterplantMarker.setMap(null); // Create the search box and link it to the UI element. var input = document.getElementById('search_input'); var searchBox = new google.maps.places.SearchBox(input); map.controls[google.maps.ControlPosition.TOP_LEFT].push(input); // Changes CSS to make search bar visible, making sure it isn't displayed before the map map.addListener('idle', function() { $("#search_input").css("display", "block"); /* General layout/CSS differences between the mobile and desktop versions. */ /* Phones and small tablets. */ if (windowWidth < 600) { $("#location_card, #resource_card").appendTo($("body")); $("#legend_card").appendTo($("map-container")); $("#resource_card #card_report_menu").on("click", function() { $(this).find("li:first-child").addClass("dropup open"); $(this).find("#report_button").attr("aria-expanded", "true"); }); } /* Large tablets and computers. */ else if (windowWidth >= 600) { $("#location_card, #resource_card").css({ "width": function() { return $("#search_input").outerWidth(); }, "top": function() { return parseInt($("#search_input").css("top")) + $("#search_input").outerHeight(true) + 10 + "px"; }, "left": function() { return parseInt($("#search_input").css("left")) + parseInt($("#search_input").css("margin-left")) + "px"; } }); $("#legend_card").css({ "width": function() { return $("#location_card").outerWidth(); }, "top": function() { //console.log(parseInt($("#search_input").css("top"))); return parseInt($("#search_input").css("top")) + $("#search_input").outerHeight(true) + 10 + "px"; }, "left": function() { return parseInt($("#location_card").css("left")) + parseInt($("#location_card").css("margin-left")) + "px"; } }); } $("#legend_card").removeClass('hide'); $("#loading_screen").addClass("hide"); }); $("#search_input").keyup(function() { if ($("#search_input").val()) activeSearch = 1; else activeSearch = 0; }); // Bias the SearchBox results towards current map's viewport. map.addListener('bounds_changed', function() { searchBox.setBounds(map.getBounds()); }); // If the map is clicked, hide the resource and location cards, show the legend map.addListener('click', function() { $("#resource_card, #location_card").hide(); $("#legend_card").show(); }); if ($pageId.indexOf("dashboard") != -1) { map.addListener('zoom_changed', function() { var zoomLvl = map.getZoom(); if (resourceActiveArray[0] == 1 && zoomLvl < 16) { leadAndPredictiveLayer.setMap(null); for (var i = 0; i < leadLayerBirdViewMarkers.length; i++) { leadLayerBirdViewMarkers[i].setMap(map); } } else if (resourceActiveArray[0] == 1 && zoomLvl >= 16) { leadAndPredictiveLayer.setMap(map); for (var i = 0; i < leadLayerBirdViewMarkers.length; i++) { leadLayerBirdViewMarkers[i].setMap(null); } } }); } // Listen for the event fired when the user selects a prediction and retrieve // more details for that place. searchBox.addListener('places_changed', function() { var places = searchBox.getPlaces(); var place = places[0]; if (places.length == 0) return; // For each place, get the icon, name and location. var bounds = new google.maps.LatLngBounds(); // Update the location marker for the address searched. locationMarker = new google.maps.Marker({map: map}); locationMarker.setTitle(place.name); locationMarker.setIcon(locationIcon); if (place.geometry.viewport) bounds.union(place.geometry.viewport); else bounds.extend(place.geometry.location); updateLocationZoom(); map.fitBounds(bounds); /* Display appropriate lead rating and message. */ var inputAddress = place.formatted_address.split(','); var streetAddress = inputAddress[0]; var query = "SELECT 'latitude', 'longitude', 'abandoned', 'leadLevel', 'testDate', 'prediction' FROM " + fusionTableAllId + " WHERE address LIKE '" + streetAddress + "' ORDER BY 'testDate' DESC"; console.log(query); window.jsonpCallbacks["searchQueryCallback"] = function(data) { if (data.rows != undefined) locationMarker.setPosition({lat: data.rows[0][0], lng: data.rows[0][1]}); else locationMarker.setPosition({lat: place.geometry.location.lat(), lng: place.geometry.location.lng()}); var content = fusionQueryCallback(data, streetAddress); createLocationCardContent("location", content); attachLocationCard("location", locationMarker, streetAddress, content); savedMarkers.push(locationMarker); savedLocationMarkers.push(locationMarker); }; queryFusionTable(query, "jsonpCallbacks.searchQueryCallback"); checkIfSaved(locationMarker.getPosition()); $("#location_card .card-action").show(); $("#location_card").show(); }); // Check the saved locations if enter is pressed while in the search box $("#search_input").on("keydown", function(event) { $("#resource_card").hide(); if (event.which == 13) updateLocationZoom(); }); // hide the location card if the search box is empty $("#search_input").on("change", function(event) { $("#resource_card").hide(); if ($(this).val() == "") $("#location_card").hide(); }); /* Show/hide buttons and dymaically set different button text. */ function updateLocationZoom() { var searched_location = $("#search_input").val(); if (map.getZoom() < 14) map.setZoom(25); else map.setZoom(20); } $("#location_card #more_info_button").on("click", function() { if ($("#more_info_button span").text() === "More Info") $("#more_info_button span").text("Less Info"); else $("#more_info_button span").text("More Info"); }); setupResourceMarkers(); } /* Search bar autocomplete. */ function initAutocomplete(inputId) { var input = document.getElementById(inputId); var autocomplete = new google.maps.places.Autocomplete(input, { bounds: new google.maps.LatLngBounds({lat: 43.021, lng: -83.681}), types: ['geocode'] }); return autocomplete; } function setUpFusionTable() { leadAndPredictiveLayer = new google.maps.FusionTablesLayer({ query: { select: "geometry", from: "1Kxo2QvMVHbNFPJQ9c9L3wbKrWQJPkbr_Gy90E2MZ" }, options: { suppressInfoWindows: "true" }, styles: [{ where: "leadLevel == -1", polygonOptions: { fillColor: "#999999", fillOpacity: 0.5, strokeColor: "#999999", strokeWeight: 1 } }, { where: "leadLevel >= 0 AND leadLevel <= 15", polygonOptions: { fillColor: "#F9D17A", fillOpacity: 1, strokeColor: "#F9D17A", strokeWeight: 3 } }, { where: "leadLevel > 15 AND leadLevel <= 150", polygonOptions: { fillColor: "#E49C49", fillOpacity: 1, strokeColor: "#E49C49", strokeWeight: 3 } }, { where: "leadLevel > 150", polygonOptions: { fillColor: "#E2692B", fillOpacity: 1, strokeColor: "#E2692B", strokeWeight: 3 } }] }); addFusionListener(leadAndPredictiveLayer); } function addFusionListener(object) { google.maps.event.addListener(object, "click", function(event) { var query = "SELECT 'latitude', 'longitude', 'abandoned', 'leadLevel', 'testDate', 'prediction' FROM " + fusionTableAllId + " WHERE address LIKE '" + event.row["address"].value + "' ORDER BY 'testDate' DESC"; // show loading screen $("#loading_screen").show(); window.jsonpCallbacks["fusionLayerQueryCallback"] = function(data) { var content = fusionQueryCallback(data, event.row["address"].value); createLocationCardContent("location", content); var latLng = "(" + event.row["latitude"].value + ", " + event.row["longitude"].value + ")"; // add hidden lat/long fields after the address $("#location_card #address").after(" "); $("#location_card #lat").html(event.row["latitude"].value); $("#location_card #lng").html(event.row["longitude"].value); checkIfSaved(latLng); map.panTo({lat: event.latLng.lat(), lng: event.latLng.lng()}); if (windowWidth >= 600 && $pageId.indexOf("dashboard") != -1) { $("#location_card").css({ left: (($("#map").width() / 2) - ($("#location_card").width() / 2)) + "px", bottom: 0 }); } // collapse expanded areas $("#previous_results button").addClass("collapsed").attr("aria-expanded", "false"); // hide loading screen $("#loading_screen").hide(); $("#location_card, #location_card .card-action").show(); }; queryFusionTable(query, "jsonpCallbacks.fusionLayerQueryCallback"); }); } function attachLegendCard() { var placeholderDetails = "Zoom in for specific lead test results.
"; attachLocationCard("leadArea", leadLevelAreaSquare, "", content); leadLayerBirdViewMarkers.push(leadLevelAreaSquare); $("#location_card .card-action").hide(); } } /* Provider Data */ else if (object == "providers.json") { js_obj = $.parseJSON(resp.body); for (i=0; i" + images + "
"; content += "" + provider.aidAddress + "
"; if (provider.phone.length > 0) content += ""; if (provider.hours.length > 0) content += "" + provider.hours + "
"; if (provider.notes.length > 0) { /* From: http://regexlib.com/REDetails.aspx?regexp_id=2841 */ var matches = provider.notes.match(/(ht|f)tp(s?)\:\/\/(([a-zA-Z0-9\-\._]+(\.[a-zA-Z0-9\-\._]+)+)|localhost)(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&%\$#_]*)?([\d\w\.\/\%\+\-\=\&\?\:\\\"\'\,\|\~\;]*)/); if (matches) { var url = matches[0]; provider.notes = provider.notes.replace(url, '' + url + ''); } content += "" + provider.notes + "
"; } if ($pageId.indexOf("dashboard") == -1) content += ""; /*If the resource is saved, display on map always if not then do not display*/ if (isSaved) isDisplayMap = map; else isDisplayMap = null; if (!isSaved) { marker = new google.maps.Marker({ position: latLng, title: title, map: isDisplayMap, icon: icon }); } else { marker = new google.maps.Marker({ position: latLng, title: title, map: isDisplayMap, icon: savedResourceIcon }); } /* Store the markers in arrays for the add/remove functionality. if saved, put in savedMarkers if not put in allMarkers*/ if (isSaved) savedMarkers.push(marker); else allMarkers.push(marker); bindInfoWindow("resource", marker, map, resourcesAvailable, content); } } /* Construction Sites */ else if (object == "construction_sites.json") { js_obj = $.parseJSON(resp.body); for (var i=0; i" + images + "
" + "" + constructStr + "
"; // Call the info window. bindInfoWindow("resource", constructionMarker, map, 'Construction', constructionContent); constructionMarkers.push(constructionMarker); } } // Uploading Pipe Data From JSON file in bucket else if (object == "pipedata.json") { js_obj = $.parseJSON(resp.body); var tempArr; for (i=0; i" + suggestedAction + "
"; } // the property only has a prediction else { content += "" + i18next.t('propertyInfo.highLevelMsg') + "
"; } content = "