Reputation: 116
I tried to find an answer to this question all over the internet. I found one similar question, but it seems no one was able to give the right answer.
while iterating it gives me the following error, "Uncaught TypeError: Cannot read property 'setProperty' of undefined". If I comment this out it will proceed the iteration until it ends but the problem is that I will not be able to use 'census_variable' as it has not been set. 4. If I change the links to point back to the US census data, it works again as expected.
Any ideas how I can solve this error? Or do you know what is causing this?
Please see the code for my map below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<title>Mashups with google.maps.Data</title>
<style>
html, body, #map { height: 100%; margin: 0; padding: 0; overflow: hidden; }
.nicebox {
position: absolute;
text-align: center;
font-family: "Roboto", "Arial", sans-serif;
font-size: 13px;
z-index: 5;
box-shadow: 0 4px 6px -4px #333;
padding: 5px 10px;
background: rgb(255,255,255);
background: linear-gradient(to bottom,rgba(255,255,255,1) 0%,rgba(245,245,245,1) 100%);
border: rgb(229, 229, 229) 1px solid;
}
#controls {
top: 10px;
left: 110px;
width: 360px;
height: 45px;
}
#data-box {
top: 10px;
left: 500px;
height: 45px;
line-height: 45px;
display: none;
}
#census-variable {
width: 360px;
height: 20px;
}
#legend { display: flex; display: -webkit-box; padding-top: 7px }
.color-key {
background: linear-gradient(to right,
hsl(5, 69%, 54%) 0%,
hsl(29, 71%, 51%) 17%,
hsl(54, 74%, 47%) 33%,
hsl(78, 76%, 44%) 50%,
hsl(102, 78%, 41%) 67%,
hsl(127, 81%, 37%) 83%,
hsl(151, 83%, 34%) 100%);
flex: 1;
-webkit-box-flex: 1;
margin: 0 5px;
text-align: left;
font-size: 1.0em;
line-height: 1.0em;
}
#data-value { font-size: 2.0em; font-weight: bold }
#data-label { font-size: 2.0em; font-weight: normal; padding-right: 10px; }
#data-label:after { content: ':' }
#data-caret { margin-left: -5px; display: none; font-size: 14px; width: 14px}
</style>
</head>
<body>
<div id="controls" class="nicebox">
<div>
<select id="census-variable">
<option value="test">Fertility rate 2015</option>
<option value="https://storage.googleapis.com/mapsdevsite/json/DP05_0017E">Median age</option>
</select>
</div>
<div id="legend">
<div id="census-min">min</div>
<div class="color-key"><span id="data-caret">◆</span></div>
<div id="census-max">max</div>
</div>
</div>
<div id="data-box" class="nicebox">
<label id="data-label" for="data-value"></label>
<span id="data-value"></span>
</div>
<div id="map"></div>
<script>
var mapStyle = [{
'stylers': [{'visibility': 'off'}]
}, {
'featureType': 'landscape',
'elementType': 'geometry',
'stylers': [{'visibility': 'on'}, {'color': '#fcfcfc'}]
}, {
'featureType': 'water',
'elementType': 'geometry',
'stylers': [{'visibility': 'on'}, {'color': '#bfd4ff'}]
}];
var map;
var censusMin = Number.MAX_VALUE, censusMax = -Number.MAX_VALUE;
function initMap() {
// load the map
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40, lng: -100},
zoom: 4,
styles: mapStyle
});
// set up the style rules and events for google.maps.Data
map.data.setStyle(styleFeature);
map.data.addListener('mouseover', mouseInToRegion);
map.data.addListener('mouseout', mouseOutOfRegion);
// wire up the button
var selectBox = document.getElementById('census-variable');
google.maps.event.addDomListener(selectBox, 'change', function() {
clearCensusData();
loadCensusData(selectBox.options[selectBox.selectedIndex].value);
});
// state polygons only need to be loaded once, do them now
loadMapShapes();
}
/** Loads the state boundary polygons from a GeoJSON source. */
function loadMapShapes() {
// load US state outline polygons from a GeoJson file
map.data.loadGeoJson('region.geojson', { idPropertyName: 'meso:name_local' });
// wait for the request to complete by listening for the first feature to be
// added
google.maps.event.addListenerOnce(map.data, 'addfeature', function() {
google.maps.event.trigger(document.getElementById('census-variable'),
'change');
});
}
/**
* Loads the census data from a simulated API call to the US Census API.
*
* @param {string} variable
*/
function loadCensusData(variable) {
// load the requested variable from the census API (using local copies)
var xhr = new XMLHttpRequest();
xhr.open('GET', variable + '.json');
xhr.onload = function() {
var censusData = JSON.parse(xhr.responseText);
censusData.shift(); // the first row contains column names
censusData.forEach(function(row) {
var censusVariable = parseFloat(row[0]);
var stateId = row[1];
console.log('StateId row[0] '+censusVariable);
console.log('censusVariable row[1] '+stateId);
// keep track of min and max values
if (censusVariable < censusMin) {
censusMin = censusVariable;
}
if (censusVariable > censusMax) {
censusMax = censusVariable;
}
// update the existing row with the new data
map.data
.getFeatureById(stateId)
.setProperty('census_variable');
});
// update and display the legend
document.getElementById('census-min').textContent =
censusMin.toLocaleString();
document.getElementById('census-max').textContent =
censusMax.toLocaleString();
};
xhr.send();
}
/** Removes census data from each shape on the map and resets the UI. */
function clearCensusData() {
censusMin = Number.MAX_VALUE;
censusMax = -Number.MAX_VALUE;
map.data.forEach(function(row) {
row.setProperty('census_variable', undefined);
});
document.getElementById('data-box').style.display = 'none';
document.getElementById('data-caret').style.display = 'none';
}
/**
* Applies a gradient style based on the 'census_variable' column.
* This is the callback passed to data.setStyle() and is called for each row in
* the data set. Check out the docs for Data.StylingFunction.
*
* @param {google.maps.Data.Feature} feature
*/
function styleFeature(feature) {
var low = [5, 69, 54]; // color of smallest datum
var high = [151, 83, 34]; // color of largest datum
// delta represents where the value sits between the min and max
var delta = (feature.getProperty('census_variable') - censusMin) /
(censusMax - censusMin);
var color = [];
for (var i = 0; i < 3; i++) {
// calculate an integer color based on the delta
color[i] = (high[i] - low[i]) * delta + low[i];
}
// determine whether to show this shape or not
var showRow = true;
if (feature.getProperty('census_variable') == null ||
isNaN(feature.getProperty('census_variable'))) {
showRow = false;
}
var outlineWeight = 0.5, zIndex = 1;
if (feature.getProperty('state') === 'hover') {
outlineWeight = zIndex = 2;
}
return {
strokeWeight: outlineWeight,
strokeColor: '#fff',
zIndex: zIndex,
fillColor: 'hsl(' + color[0] + ',' + color[1] + '%,' + color[2] + '%)',
fillOpacity: 0.75,
visible: showRow
};
}
/**
* Responds to the mouse-in event on a map shape (state).
*
* @param {?google.maps.MouseEvent} e
*/
function mouseInToRegion(e) {
// set the hover state so the setStyle function can change the border
e.feature.setProperty('state', 'hover');
var percent = (e.feature.getProperty('census_variable') - censusMin) /
(censusMax - censusMin) * 100;
// update the label
document.getElementById('data-label').textContent =
e.feature.getProperty('NAME');
document.getElementById('data-value').textContent =
e.feature.getProperty('census_variable').toLocaleString();
document.getElementById('data-box').style.display = 'block';
document.getElementById('data-caret').style.display = 'block';
document.getElementById('data-caret').style.paddingLeft = percent + '%';
}
/**
* Responds to the mouse-out event on a map shape (state).
*
* @param {?google.maps.MouseEvent} e
*/
function mouseOutOfRegion(e) {
// reset the hover state, returning the border to normal
e.feature.setProperty('state', 'normal');
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=API_KEY&callback=initMap">
</script>
</body>
</html>
Here is my JSON file with Census Data (test.json):
[["DP02_0066PE","region"],
["2.31", "Adana"],
["2.86", "Adıyaman"],
["2.06", "Afyonkarahisar"],
["3.80", "Ağrı"],
["2.24", "Aksaray"],
["1.79", "Amasya"],
["1.76", "Ankara"],
["1.96", "Antalya"],
["2.15", "Ardahan"],
["1.73", "Artvin"],
["1.85", "Aydın"],
["1.64", "Balıkesir"],
["1.58", "Bartın"],
["3.24", "Batman"],
["2.07", "Bayburt"],
["1.71", "Bilecik"],
["2.42", "Bingöl"],
["3.40", "Bitlis"],
["1.59", "Bolu"],
["1.77", "Burdur"],
["1.91", "Bursa"],
["1.53", "Çanakkale"],
["1.77", "Çankırı"],
["1.83", "Çorum"],
["1.84", "Denizli"],
["3.21", "Diyarbakır"],
["1.85", "Düzce"],
["1.53", "Edirne"],
["1.97", "Elazığ"],
["1.82", "Erzincan"],
["2.51", "Erzurum"],
["1.55", "Eskişehir"],
["3.15", "Gaziantep"],
["1.62", "Giresun"],
["1.66", "Gümüşhane"],
["2.69", "Hakkâri"],
["2.70", "Hatay"],
["3.04", "Iğdır"],
["1.70", "Isparta"],
["1.88", "İstanbul"],
["1.72", "İzmir"],
["2.61", "Kahramanmaraş"],
["1.56", "Karabük"],
["2.10", "Karaman"],
["2.64", "Kars"],
["1.62", "Kastamonu"],
["2.18", "Kayseri"],
["2.92", "Kilis"],
["1.71", "Kırıkkale"],
["1.54", "Kırklareli"],
["1.79", "Kırşehir"],
["2.06", "Kocaeli"],
["2.18", "Konya"],
["1.58", "Kütahya"],
["2.01", "Malatya"],
["1.92", "Manisa"],
["3.41", "Mardin"],
["2.15", "Mersin"],
["1.75", "Muğla"],
["3.45", "Muş"],
["1.96", "Nevşehir"],
["2.18", "Niğde"],
["1.81", "Ordu"],
["2.47", "Osmaniye"],
["1.78", "Rize"],
["1.92", "Sakarya"],
["1.80", "Samsun"],
["4.38", "Şanlıurfa"],
["3.55", "Siirt"],
["1.72", "Sinop"],
["4.01", "Şırnak"],
["1.96", "Sivas"],
["1.93", "Tekirdağ"],
["1.72", "Tokat"],
["1.85", "Trabzon"],
["1.69", "Tunceli"],
["1.73", "Uşak"],
["3.36", "Van"],
["1.77", "Yalova"],
["1.99", "Yozgat"],
["1.55", "Zonguldak"]]
The other file with all the geoJSON data is way too big to post here. But if necessary I can find a way to share it with you.
Upvotes: 0
Views: 10599
Reputation: 116
I finally figured it out. To be frank, it was a pretty stupid mistake from my part. I guess I was already tired and didn't realize my mistake so I'd like to thank everyone who commented on my question as it helped me realize what I did wrong.
There are two JSON files. One that contains the coordinates, let's call it coordinates.geojson and the other contains the census data, let's call it census.json.
Now for these lines of code to work,
map.data
.getFeatureById(stateId)
.setProperty('census_variable');
you must make sure that stateId corresponds to both the id in the census.json file as well as the id in the coordinates.geojson file.
In my case the stateId from the census.json file did not equal the first id/state in coordinates.geojson which was Aydin. Whereas census.json started with Adana, then Adıyaman etc.
Therefore I had to change the order of the census data to
[["DP02_0066PE","region"],
["1.85", "Aydin"],
["1.72", "Izmir"],
["1.64", "Balikesir"],
["1.53", "Çanakkale"],
["1.53", "Edirne"],
["1.54", "Kirklareli"],
["1.93", "Tekirdag"],
["1.71", "Bilecik"],
["1.91", "Bursa"],
["1.88", "Istanbul"],
["2.06", "Kocaeli"],
["1.92", "Sakarya"],
["1.59", "Bolu"],
["1.55", "Eskisehir"],
["1.62", "Kastamonu"],
["1.96", "Antalya"],
["2.06", "Afyon"],
["1.77", "Burdur"],
["1.84", "Denizli"],
["1.70", "Isparta"],
["1.58", "Kütahya"],
["1.92", "Manisa"],
["1.75", "Mugla"],
["2.86", "Adiyaman"],
["1.97", "Elazig"],
["2.61", "Kahramanmaras"],
["2.01", "Malatya"],
["2.15", "Içel"],
["1.79", "Kirsehir"],
["2.18", "Kayseri"],
["1.96", "Nevsehir"],
["2.70", "Hatay"],
["1.79", "Amasya"],
["1.83", "Çorum"],
["1.62", "Giresun"],
["1.81", "Ordu"],
["1.72", "Sinop"],
["1.96", "Sivas"],
["1.80", "Samsun"],
["1.72", "Tokat"],
["1.73", "Artvin"],
["2.51", "Erzurum"],
["1.82", "Erzincan"],
["1.78", "Rize"],
["1.85", "Trabzon"],
["3.80", "Agri"],
["2.42", "Bingöl"],
["3.21", "Diyarbakir"],
["3.45", "Mus"],
["3.40", "Bitlis"],
["1.76", "Ankara"],
["1.77", "Çankiri"],
["1.55", "Zonguldak"],
["2.18", "Konya"],
["2.10", "Karaman"],
["1.73", "Usak"],
["3.15", "Gaziantep"],
["4.38", "Sanliurfa"],
["2.31", "Adana"],
["1.71", "Kirikkale"],
["2.18", "Nigde"],
["2.24", "Aksaray"],
["1.99", "Yozgat"],
["1.66", "Gümüshane"],
["2.07", "Bayburt"],
["2.64", "Kars"],
["3.41", "Mardin"],
["3.24", "Batman"],
["3.55", "Siirt"],
["4.01", "Sirnak"],
["1.69", "Tunceli"],
["2.69", "Hakkari"],
["3.36", "Van"],
["2.15", "Ardahan"],
["3.04", "Igdir"],
["2.92", "Kilis"],
["2.47", "Osmaniye"],
["1.77", "Yalova"],
["1.85", "Düzce"],
["1.56", "Karabük"],
["1.58", "Bartin"]]
Last but not least, please note that I removed all the specific Turkish characters such as ğ, ı and ş because the id from coordinates.geojson where spelled without them. Hence I changed Ağrı to Agri and so forth.
I guess it would have been better had I used numbers as IDs instead of names.
I hope this will prevent other people of making the same mistake.
Upvotes: 1