Entire map implementation js file
(function($){
/*******************************************
Set your namespaced functions as non global variables,
keep the global scope clear to reduce naming clashes and keep memory usage down
jQuery 1.5 or higher.
*******************************************/
var nsmap = nsmap || {};
///////////////////////////////////
/* Drupal.behaviors will get called when the DOM has loaded */
Drupal.behaviors.maps = {
attach:function (context, settings) {
// Set name spaced variables
nsmap.mapSettings = settings.mapSettings;
nsmap.basePath = settings.mapSettings.fullModulePath; // path to geodata file
nsmap.serviceRegions = settings.mapSettings.serviceRegions; // regions from form
nsmap.geoLocations = settings.mapSettings.geoLocations; // All taxonomy locations with parents
nsmap.officeLocation = settings.mapSettings.officeLoc; // Office Location
nsmap.bounds = '';
nsmap.initialPosition = {};
nsmap.zoomed = false;
// Collection object
nsmap.allFeaturesToSearch = {
type: 'FeatureCollection',
features: []
};
//console.log(JSON.stringify(nsmap.geoLocations))
// Init Function
nsmap.mapInit = function() {
var L = window.L;
// check that the Leaflet library is available
if (!L) {
console.error('Missing the Leaflet library')
return false;
} else {
//check that the dom element exists before attaching to it
if ( $('#lmapDetail', context) ){
//console.log('yes----', $('#lmapDetail', context));
var map = new L.map('lmapDetail', { minZoom: 2 });
// Initial Position
map.setView(new L.LatLng(37.500, -100.000), 4);
// Add Footer
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
//attribution: 'Test Overlay'
}).addTo(map);
//turn off features
map.scrollWheelZoom.disable();
//map.touchZoom.disable();
//map.doubleClickZoom.disable();
//map.boxZoom.disable();
//map.keyboard.disable();
//$(".leaflet-control-zoom").css("visibility", "hidden");
// serviceRegions passed via drupal settings
if(nsmap.serviceRegions) {
nsmap.getFeatures( map, nsmap.serviceRegions, function(result){
var featuresForSelectedStatesObj = result;
nsmap.buildStateLayer(map, featuresForSelectedStatesObj);
// add office marker
if(nsmap.officeLocation) {
//console.log('add office, officeLocation= ', nsmap.officeLocation);
nsmap.addOfficeMarker(map, nsmap.officeLocation);
}
});
} else {
console.error('serviceRegions not found');
}; // if nsmap.serviceRegions
} else {
console.error('dom element lmapDetail does not exist');
} // if $('#lmapDetail
}
}// end mapInit
// nsmap.dynamicBasePath = 'http://' + window.location.hostname + '/geoJSON';
// Get the features to add to the map
nsmap.getFeatures = function (thisMap, statesSelected, callback){
var map = thisMap;
var theStates = statesSelected;
var featureFilePath = this.basePath + '/data/us-states.js';
var provinceFilePath = this.basePath + '/data/canada.json';
// empty feature collection to add geojson
var colObj = {
type: 'FeatureCollection',
features: []
};
// Step 1 get the us-state features
getUSfCollection(featureFilePath, function(errorMessage, usresults) {
if (errorMessage){
console.error('getUSfCollection failed: US state file is a dependency for mapping.');
callback('getUSfCollection failed');
};
nsmap.allFeaturesToSearch.features = nsmap.allFeaturesToSearch.features.concat(usresults.features); // all the state shapes
// Step 2 get the Canada features
getCanadafCollection(provinceFilePath, function(canresults) {
nsmap.allFeaturesToSearch.features = nsmap.allFeaturesToSearch.features.concat(canresults.features);
// We have all the features, now apply to the selected states
for (var i = theStates.length - 1; i >= 0; i--) {
//console.log('getFeatures - theStates[i]', theStates[i]);
var aStateNameToFind = theStates[i].name.toUpperCase() ;
var featureArray = nsmap.allFeaturesToSearch.features;
if ($.type(featureArray) === "array") {
// Loop Features and find either a canadian province or a US state
for (var j = featureArray.length - 1; j >= 0; j--) {
var featureNameUS = featureArray[j].properties.name ;
var featureNameCanada = featureArray[j].properties.NAME ;
var featureNameFound = '';
if(featureNameUS ){
featureNameFound = featureNameUS.toUpperCase();
} else if (featureNameCanada) {
featureNameFound = featureNameCanada.toUpperCase();
};
if (featureNameFound ){
if (aStateNameToFind == featureNameFound){
//console.log('-getFeatures - matched a location, now get the details');
// Collect the parent info (for coloring etc)
// Note: now we only get one parent per item, no need to loop.
findByNameGetParents(featureNameFound, function(parent){
var parentArray = parent; // Assuming just one parent
//console.log('returned parent TID: ', parentArray);
findParentByTID(parentArray, function(parentObject){
if (parentObject) {
//console.log('Returned Parent Object: ', parentObject);
featureArray[j].properties.parent = parentObject.name;
//console.log('Added Parent to featureArray[j]', featureArray[j]);
}
}); //findParentByTIDFromID
}); //findByNameGetParents
// push it to the collection
colObj.features.push(featureArray[j]);
};
};
}; // for feature
} else {
console.error('featureArray is not available');
}
}// for state
callback(colObj);
})//getCanadafCollection
})//getUSfCollection
}//getFeatures
// Loop the location taxonomy terms and get the parent
function findByNameGetParents(featureNameFound, callback){
// get the locations to look for parents in.
var locations = nsmap.geoLocations;
//console.log('findByNameGetParents', featureNameFound);
for (var i = locations.length - 1; i >= 0; i--) {
if (locations[i].name.toUpperCase() == featureNameFound) {
//console.log(locations[i].parents);
callback(locations[i].parents);
}
};
} //findByNameGetParents
function findParentByTID(parents, callback){
var locations = nsmap.geoLocations;
var parentsArray = parents;
// Usually just one parent
if (!parentsArray.length === 1) {
// So far there is only one parent object, this is here as a test.
console.warn('parentsArray.length != 1, unusual, test: get all parents?');
}
// Return just the first parent, always just one so far.
//console.log('findParent-parentsArray', parentsArray[0]);
var parentTID = parentsArray[0]
// loop the object and match the TID
for (var i = locations.length - 1; i >= 0; i--) {
if (locations[i].tid == parentTID) {
//console.log('-findParentByTID parentInfo:', locations[i]);
//console.log(locations[i].name);
callback(locations[i]);
}
};
} //findParentByTID
// Get the us-state features array
function getUSfCollection(featureFilePath, callback){
var stateFile = featureFilePath;
// state file is .js so...
$.getScript( stateFile )
.done(function( script, textStatus ) {
callback(null, statesData);
})
.fail(function( jqxhr, settings, exception ) {
console.error(" Error getting stateFile.", exception)
callback("Cannot reach stateFile " + exception);
return false;
});
} //getUSfCollection
// Get the us-state features array
function getCanadafCollection(provinceFilePath, callback){
var provinceFile = provinceFilePath;
// state file is json so...
$.getJSON(provinceFile, function(data) {
callback(data);
})//function(data)
.fail(function() {
console.error( "getCanadafCollection getJSON error!" );
});
} //getCanadafCollection
/////////////////////////////
// Process the state layer
nsmap.buildStateLayer = function (map, stateData) {
//console.log('buildStateLayer stateData', stateData);
var geojsonStates = L.geoJson(stateData, {
style: function (feature) {
return nsmap.styleMap(feature);
},
onEachFeature: function (feature, layer) {
//layer.on({
//mouseover: highlightFeature,
//mouseout: resetHighlight,
//click: zoomToFeature,
//pointToLayer: pointToLayer
//});
},
});//end geojsonStates
// put all state layers into a group
var stateOverlay = L.featureGroup([geojsonStates])
//.bindPopup('Hello world!')
.on('click', onOverlayClick);
stateOverlay.addTo(map);
function onOverlayClick(){
//console.log('onOverlayClick', this);
if (nsmap.zoomed === true){
//console.log('Zooming out');
map.setView(new L.LatLng(nsmap.initialPosition.groupCenter.lat, nsmap.initialPosition.groupCenter.lng), nsmap.initialPosition.groupZoom);
nsmap.zoomed = false;
}
};
//var id_stateOverlay = map.getLayerId(stateOverlay);
//geojsonStates.addTo(map);
// Option to set maxZoom with
var zoomOverride = map.getZoom();
nsmap.bounds = geojsonStates.getBounds()
map.fitBounds(nsmap.bounds, { maxZoom: 4 });
nsmap.addLegend(map);
//addRolloverControl();
}//END buildStateLayer()
// Color the states
nsmap.styleMap = function(feature) {
// Map Colors
this.colors = {
grey : "rgba(84,96,101,0.3)", //#546065",
// colorblind colors
blue: "rgba(21, 21, 119, 0.3)", //#151577
orange: "rgba(255, 109, 2, 0.3)", //#ff6d02
green: "rgba(50, 82, 16, 0.3)", //#325210
yellowgreen: "rgba(216, 205, 24, 0.3)", //#d8cd18
darkorange: "rgba(144, 16, 243, 0.3)", //#9010f3
};
var colorVar = '#7AAD42';
// Old non-colorblind colors - for reference
// blue : "rgba(108,157,179,0.3)", //"#6c9db3",
// orange : "rgba(247,148,30,0.3)", //"#f7941e",
// green : "rgba(122,173,66,0.3)", //#7aad42",
// yellowgreen : "rgba(234,234,100,0.3)",//"#d1d179",
// darkorange : "rgba(188,47,80,0.3)", //#bc2f50", // too close to other orange, added red
// //darkorange : "rgba(182, 109, 16, 0.3)", //#bc2f50",
if (feature.properties.parent){
//console.log('feature has a parent= ', feature.properties.parent);
switch (feature.properties.parent) {
// Midwest
case "East North Central":
var colorVar = this.colors.orange;
break;
case 'West North Central':
var colorVar = this.colors.orange;
break;
// Northeast
case "New England":
var colorVar = this.colors.darkorange;
break;
case 'Mid-Atlantic':
var colorVar = this.colors.darkorange;
break;
// South
case "East South Central":
var colorVar = this.colors.green;
break;
case 'South Atlantic':
var colorVar = this.colors.green;
break;
case 'West South Central':
var colorVar = this.colors.green;
break;
// West
case "Mountain":
var colorVar = this.colors.blue;
break;
case 'Pacific':
var colorVar = this.colors.blue;
break;
// Canada
case "Canada":
var colorVar = this.colors.yellowgreen;
break;
//
default:
var colorVar = this.colors.grey;
}
}//if (feature.properties.parent
return {
fillColor: colorVar,
weight: 1,
opacity: 1.0,
color: "#a0a0a0",
dashArray: '3',
fillOpacity: 0.6,
className: "statePolygon",
};
} //end styleMap
/////////////////////////////
/// LEGEND
nsmap.addLegend = function (map) {
var colors = this.colors;
var mapLegend = L.control({position:'bottomleft'});
mapLegend.onAdd = function (map) {
// create the control container div with classes
var container = L.DomUtil.create('div', 'info legend');
var html = '<h5 class="legend" style="margin-bottom: 0.1rem; padding:0px 10px; ">Regions</h5>';
html += ' <p class="midwest" style="color:#444444; background-color:' + colors.orange + '; padding:0px 10px; margin-bottom: 0px;">Midwest</p> ';
html += ' <p class="northeast" style="color:#444444; background-color:' + colors.darkorange + '; padding:0px 10px; margin-bottom: 0px;">Northeast</p> ';
html += ' <p class="south" style="color:#444444; background-color:' + colors.green + '; padding:0px 10px; margin-bottom: 0px;">South</p> ';
html += ' <p class="west" style="color:#444444; background-color:'+ colors.blue + '; padding:0px 10px; margin-bottom: 0px;">West</p> ';
html += ' <p class="canada" style="color:#444444; background-color:' + colors.yellowgreen + '; padding:0px 10px; margin-bottom: 0px;">Canada</p> ';
container.innerHTML = html;
return container;
};
mapLegend.addTo(map);
}
/////////////////////////////
// Add the Office marker
nsmap.addOfficeMarker = function (map, coordinates) {
var longitude = coordinates.lon;
var latitude = coordinates.lat;
//This uses Leaflet.js's markers:
var officeMarker = L.divIcon({
iconSize: [2, 20],
iconAnchor: [20, 30],
className: 'comment',
html: '<i class="fi-marker medium"></i>'
});
var marker = L.marker([latitude, longitude], {icon: officeMarker}).addTo(map);
// Popup
//marker.bindPopup("<b>Hello world!</b><br>I am a popup.").openPopup();
// map.on('click', function(e) {
// console.log(this);
// //console.log(nsmap.bounds);
// //map.fitBounds(nsmap.bounds);
// }
marker.on('click', function(e) {
// TODO - toggle click function for zoom and reset
//console.log('nsmap.initialPosition', nsmap.initialPosition);
if (nsmap.zoomed === false){
//console.log('Zooming in');
nsmap.initialPosition.groupCenter = map.getCenter();
nsmap.initialPosition.groupZoom = map.getZoom();
map.setView(new L.LatLng(e.latlng.lat, e.latlng.lng), 9);
nsmap.zoomed = true;
} else {
//console.log('Zooming out');
map.setView(new L.LatLng(nsmap.initialPosition.groupCenter.lat, nsmap.initialPosition.groupCenter.lng), nsmap.initialPosition.groupZoom);
nsmap.zoomed = false;
}
//map.panTo(new L.LatLng(40.737, -73.923));
});
// capture map click
map.on('click', onMapClick);
function onMapClick(){
//console.log('initialPosition', nsmap.initialPosition);
if (nsmap.zoomed === true){
//console.log('Zooming out');
map.setView(new L.LatLng(nsmap.initialPosition.groupCenter.lat, nsmap.initialPosition.groupCenter.lng), nsmap.initialPosition.groupZoom);
nsmap.zoomed = false;
}
};
// click action
// var popup = L.popup();
// function onMapClick(e) {
// popup
// .setLatLng(e.latlng)
// .setContent("You clicked the map at " + e.latlng.toString())
// .openOn(map);
// }
}//END addOfficeMarker()
//call init function
nsmap.mapInit();
}//attach:function (context, settings)
};//Drupal.behaviors.maps
})(jQuery);