Created
May 1, 2018 02:52
-
-
Save cormundo/b7703bb55b8a74d19caa0ebf75c856cf to your computer and use it in GitHub Desktop.
// source https://jsbin.com
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<title>Contractors</title> | |
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.js'></script> | |
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.css' rel='stylesheet' | |
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.0.1/mapbox-gl-geocoder.js'></script> | |
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.0.1/mapbox-gl-geocoder.css' type='text/css' /> | |
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script> | |
<style> | |
body { | |
color: #404040; | |
font: 400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif; | |
margin: 0; | |
padding: 0; | |
-webkit-font-smoothing: antialiased; | |
} | |
* { | |
-webkit-box-sizing: border-box; | |
-moz-box-sizing: border-box; | |
box-sizing: border-box; | |
} | |
h1 { | |
font-size: 22px; | |
margin: 0; | |
font-weight: 400; | |
line-height: 20px; | |
padding: 20px 2px; | |
} | |
a { | |
color: #404040; | |
text-decoration: none; | |
} | |
a:hover { | |
color: #101010; | |
} | |
.sidebar { | |
position: absolute; | |
width: 33.3333%; | |
height: 100%; | |
top: 0; | |
left: 0; | |
overflow: hidden; | |
border-right: 1px solid rgba(0, 0, 0, 0.25); | |
} | |
.pad2 { | |
padding: 0px; | |
} | |
.map { | |
position: absolute; | |
left: 33.3333%; | |
width: 66.6666%; | |
top: 0; | |
bottom: 0; | |
} | |
.heading { | |
background: #fff; | |
border-bottom: 1px solid #eee; | |
height: 60px; | |
line-height: 60px; | |
padding: 0 10px; | |
} | |
.listings { | |
height: 100%; | |
overflow: auto; | |
padding-bottom: 60px; | |
} | |
.listings .item { | |
display: block; | |
border-bottom: 1px solid #eee; | |
padding: 10px; | |
text-decoration: none; | |
} | |
.listings .item:last-child { border-bottom: none; } | |
.listings .item .title { | |
display: block; | |
color: #00853e; | |
font-weight: 700; | |
} | |
.listings .item .title small { font-weight: 400; } | |
.listings .item.active .title, | |
.listings .item .title:hover { color: #8cc63f; } | |
.listings .item.active { | |
background-color: #f8f8f8; | |
} | |
::-webkit-scrollbar { | |
width: 3px; | |
height: 3px; | |
border-left: 0; | |
background: rgba(0, 0, 0, 0.1); | |
} | |
::-webkit-scrollbar-track { | |
background: none; | |
} | |
::-webkit-scrollbar-thumb { | |
background: #00853e; | |
border-radius: 0; | |
} | |
.clearfix { display: block; } | |
.clearfix::after { | |
content: '.'; | |
display: block; | |
height: 0; | |
clear: both; | |
visibility: hidden; | |
} | |
.marker { | |
position: absolute; | |
cursor: pointer; | |
height: 20px; | |
width: 20px; | |
background-image: url('QCleaf3.png'); | |
background-color: rgba(0, 0, 0, 0); | |
} | |
.mapboxgl-popup-close-button { | |
display: circle; | |
} | |
.mapboxgl-popup-content { | |
font: 400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif; | |
padding: 5; | |
width: 180px; | |
} | |
.mapboxgl-popup-content-wrapper { | |
padding: 5%; | |
} | |
.mapboxgl-popup-content h3 { | |
background: #3d8c51; | |
color: #d0f2cb; | |
margin: 1; | |
display: block; | |
padding: 15px; | |
border-radius: 5px 5px 5px 5px; | |
font-weight: 600; | |
margin-top: 0px; | |
} | |
.mapboxgl-popup-content h4 { | |
margin: 1; | |
display: block; | |
padding: 14px; | |
margin-top: 5px; | |
font-weight: 400; | |
background: #e1ede1; | |
} | |
.mapboxgl-popup-content div { | |
padding: 10px; | |
} | |
.mapboxgl-container .leaflet-marker-icon { | |
cursor: pointer; | |
} | |
.mapboxgl-popup-anchor-top > .mapboxgl-popup-content { | |
margin-top: 15px; | |
} | |
.mapboxgl-popup-anchor-top > .mapboxgl-popup-tip { | |
border-bottom-color: #91c949; | |
} | |
a:link { | |
color: black; | |
background-color: transparent; | |
text-decoration: none; | |
} | |
a:visited { | |
color: black; | |
background-color: transparent; | |
text-decoration: none; | |
} | |
a:hover { | |
color: black; | |
background-color: transparent; | |
text-decoration: underline; | |
} | |
a:active { | |
color: black; | |
background-color: transparent; | |
text-decoration: underline; | |
} | |
.mapboxgl-ctrl-geocoder { | |
border: 0; | |
border-radius: 0; | |
position: relative; | |
top: 0; | |
width: 800px; | |
margin-top: 0; | |
} | |
.mapboxgl-ctrl-geocoder > div { | |
min-width: 100%; | |
margin-left: 0; | |
} | |
</style> | |
<body> | |
<div class='sidebar'> | |
<div class='heading'> | |
<h1>Quiet Contractors</h1> | |
</div> | |
<div id='listings' class='listings'></div> | |
</div> | |
<div id='map' class='map pad2'> | |
</div> | |
<script> | |
if (!('remove' in Element.prototype)) { | |
Element.prototype.remove = function() { | |
if (this.parentNode) { | |
this.parentNode.removeChild(this); | |
} | |
}; | |
} | |
mapboxgl.accessToken = 'pk.eyJ1IjoiY2RpY2tpbnNvbjExIiwiYSI6ImNqY3J6eDlscTBweHMycXMwcWltbnRiN3MifQ.X68p3M-5wwH3AudbxEYdfw'; | |
var map = new mapboxgl.Map({ | |
container: 'map', | |
style: 'mapbox://styles/cdickinson11/cjg6j2hvr112u2rqgqfbdxpqg', | |
center: [-71.3039, 42.4259], | |
zoom: 8, | |
maxZoom: 11, | |
minZoom: 5, | |
cluster: true, | |
}); | |
var stores = 'MasterDirectory_QC_V10.geojson'; | |
map.on('load', function (e) { | |
map.addSource('places', { | |
type: 'geojson', | |
data: 'stores' | |
}); | |
buildLocationList(stores); | |
var geocoder = new MapboxGeocoder({ | |
accessToken: mapboxgl.accessToken, | |
bbox: [-124.848974, 24.396308 , -66.885444, 49.384358] | |
}); | |
map.addControl(geocoder, 'top-right'); | |
map.addSource('single-point', { | |
type: 'geojson', | |
data: { | |
type: 'FeatureCollection', | |
features: [] | |
} | |
}); | |
map.addLayer({ | |
id: 'point', | |
source: 'single-point', | |
type: 'circle', | |
paint: { | |
'circle-radius': 7, | |
'circle-color': '#00853e', | |
'circle-stroke-width': 3, | |
'circle-stroke-color': '#f2822d' | |
} | |
}); | |
geocoder.on('result', function(ev) { | |
var searchResult = ev.result.geometry; | |
map.getSource('single-point').setData(searchResult); | |
var options = { units: 'miles' }; | |
stores.features.forEach(function(store) { | |
Object.defineProperty(store.properties, 'distance', { | |
value: turf.distance(searchResult, store.geometry, options), | |
writable: true, | |
enumerable: true, | |
configurable: true | |
}); | |
stores.features.sort(function(a, b) { | |
if (a.properties.distance > b.properties.distance) { | |
return 1; | |
} | |
if (a.properties.distance < b.properties.distance) { | |
return -1; | |
} | |
return 0; | |
}); | |
var listings = document.getElementById('listings'); | |
while (listings.firstChild) { | |
listings.removeChild(listings.firstChild); | |
} | |
function sortLonLat(storeIdentifier) { | |
var lats = [stores.features[storeIdentifier].geometry.coordinates[1], searchResult.coordinates[1]]; | |
var lons = [stores.features[storeIdentifier].geometry.coordinates[0], searchResult.coordinates[0]]; | |
var sortedLons = lons.sort(function(a, b) { | |
if (a > b) { | |
return 1; | |
} | |
if (a.distance < b.distance) { | |
return -1; | |
} | |
return 0; | |
}); | |
var sortedLats = lats.sort(function(a, b) { | |
if (a > b) { | |
return 1; | |
} | |
if (a.distance < b.distance) { | |
return -1; | |
} | |
return 0; | |
}); | |
map.fitBounds([ | |
[sortedLons[0], sortedLats[0]], | |
[sortedLons[1], sortedLats[1]] | |
], { | |
padding: 100 | |
}); | |
} | |
sortLonLat(0); | |
createPopUp(stores.features[0]); | |
buildLocationList(stores); | |
}); | |
}); | |
}); | |
stores.features.forEach(function(marker, i) { | |
var el = document.createElement('div'); | |
el.id="marker-"+i; | |
el.className = 'marker'; | |
el.collision = 'true'; | |
new mapboxgl.Marker(el, { offset: [6, 15] }) | |
.setLngLat(marker.geometry.coordinates) | |
.addTo(map); | |
el.addEventListener('click', function(e) { | |
var activeItem = document.getElementsByClassName('active'); | |
flyToStore(marker); | |
createPopUp(marker); | |
e.stopPropagation(); | |
if (activeItem[0]) { | |
activeItem[0].classList.remove('active'); | |
} | |
var listing = document.getElementById('listing-' + i); | |
console.log(listing); | |
listing.classList.add('active'); | |
}); | |
}); | |
function flyToStore(currentFeature) { | |
map.flyTo({ | |
center: currentFeature.geometry.coordinates, | |
zoom: 11 | |
}); | |
} | |
function createPopUp(currentFeature) { | |
var popUps = document.getElementsByClassName('mapboxgl-popup'); | |
if (popUps[0]) popUps[0].remove(); | |
var popup = new mapboxgl.Popup({closeOnClick: false}) | |
.setLngLat(currentFeature.geometry.coordinates) | |
.setHTML('<h3><a href=' + currentFeature.properties.URL2 + '>' + currentFeature.properties.Company + '</a></h4>'+ ' · ' + currentFeature.properties.City + ", " + currentFeature.properties.State + '</p>' + ' · ' + "Phone: " + currentFeature.properties.Phone + '</p>') | |
.addTo(map); | |
} | |
function buildLocationList(data) { | |
for (i = 0; i < data.features.length; i++) { | |
var currentFeature = data.features[i]; | |
var prop = currentFeature.properties; | |
var listings = document.getElementById('listings'); | |
var listing = listings.appendChild(document.createElement('div')); | |
listing.className = 'item'; | |
listing.id = "listing-" + i; | |
var link = listing.appendChild(document.createElement('a')); | |
link.href = '#'; | |
link.className = 'title'; | |
link.dataPosition = i; | |
link.innerHTML = prop.Company; | |
var details = listing.appendChild(document.createElement('div')); | |
details.innerHTML = prop.City + ', ' + prop.State; | |
if (prop.Phone) { | |
details.innerHTML += ' · ' + prop.Phone; | |
} | |
if (prop.distance) { | |
var roundedDistance = Math.round(prop.distance * 100) / 100; | |
details.innerHTML += '<p><strong>' + roundedDistance + ' miles away</strong></p>'; | |
} | |
link.addEventListener('click', function(e) { | |
var clickedListing = data.features[this.dataPosition]; | |
flyToStore(clickedListing); | |
createPopUp(clickedListing); | |
var activeItem = document.getElementsByClassName('active'); | |
if (activeItem[0]) { | |
activeItem[0].classList.remove('active'); | |
} | |
this.parentNode.classList.add('active'); | |
}); | |
} | |
} | |
</script> | |
<script id="jsbin-source-html" type="text/html"><title>Contractors</title> | |
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.js'><\/script> | |
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.css' rel='stylesheet' | |
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.0.1/mapbox-gl-geocoder.js'><\/script> | |
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.0.1/mapbox-gl-geocoder.css' type='text/css' /> | |
<script src='https://npmcdn.com/@turf/turf/turf.min.js'><\/script> | |
<style> | |
body { | |
color: #404040; | |
font: 400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif; | |
margin: 0; | |
padding: 0; | |
-webkit-font-smoothing: antialiased; | |
} | |
* { | |
-webkit-box-sizing: border-box; | |
-moz-box-sizing: border-box; | |
box-sizing: border-box; | |
} | |
h1 { | |
font-size: 22px; | |
margin: 0; | |
font-weight: 400; | |
line-height: 20px; | |
padding: 20px 2px; | |
} | |
a { | |
color: #404040; | |
text-decoration: none; | |
} | |
a:hover { | |
color: #101010; | |
} | |
.sidebar { | |
position: absolute; | |
width: 33.3333%; | |
height: 100%; | |
top: 0; | |
left: 0; | |
overflow: hidden; | |
border-right: 1px solid rgba(0, 0, 0, 0.25); | |
} | |
.pad2 { | |
padding: 0px; | |
} | |
.map { | |
position: absolute; | |
left: 33.3333%; | |
width: 66.6666%; | |
top: 0; | |
bottom: 0; | |
} | |
.heading { | |
background: #fff; | |
border-bottom: 1px solid #eee; | |
height: 60px; | |
line-height: 60px; | |
padding: 0 10px; | |
} | |
.listings { | |
height: 100%; | |
overflow: auto; | |
padding-bottom: 60px; | |
} | |
.listings .item { | |
display: block; | |
border-bottom: 1px solid #eee; | |
padding: 10px; | |
text-decoration: none; | |
} | |
.listings .item:last-child { border-bottom: none; } | |
.listings .item .title { | |
display: block; | |
color: #00853e; | |
font-weight: 700; | |
} | |
.listings .item .title small { font-weight: 400; } | |
.listings .item.active .title, | |
.listings .item .title:hover { color: #8cc63f; } | |
.listings .item.active { | |
background-color: #f8f8f8; | |
} | |
::-webkit-scrollbar { | |
width: 3px; | |
height: 3px; | |
border-left: 0; | |
background: rgba(0, 0, 0, 0.1); | |
} | |
::-webkit-scrollbar-track { | |
background: none; | |
} | |
::-webkit-scrollbar-thumb { | |
background: #00853e; | |
border-radius: 0; | |
} | |
.clearfix { display: block; } | |
.clearfix::after { | |
content: '.'; | |
display: block; | |
height: 0; | |
clear: both; | |
visibility: hidden; | |
} | |
.marker { | |
position: absolute; | |
cursor: pointer; | |
height: 20px; | |
width: 20px; | |
background-image: url('QCleaf3.png'); | |
background-color: rgba(0, 0, 0, 0); | |
} | |
.mapboxgl-popup-close-button { | |
display: circle; | |
} | |
.mapboxgl-popup-content { | |
font: 400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif; | |
padding: 5; | |
width: 180px; | |
} | |
.mapboxgl-popup-content-wrapper { | |
padding: 5%; | |
} | |
.mapboxgl-popup-content h3 { | |
background: #3d8c51; | |
color: #d0f2cb; | |
margin: 1; | |
display: block; | |
padding: 15px; | |
border-radius: 5px 5px 5px 5px; | |
font-weight: 600; | |
margin-top: 0px; | |
} | |
.mapboxgl-popup-content h4 { | |
margin: 1; | |
display: block; | |
padding: 14px; | |
margin-top: 5px; | |
font-weight: 400; | |
background: #e1ede1; | |
} | |
.mapboxgl-popup-content div { | |
padding: 10px; | |
} | |
.mapboxgl-container .leaflet-marker-icon { | |
cursor: pointer; | |
} | |
.mapboxgl-popup-anchor-top > .mapboxgl-popup-content { | |
margin-top: 15px; | |
} | |
.mapboxgl-popup-anchor-top > .mapboxgl-popup-tip { | |
border-bottom-color: #91c949; | |
} | |
a:link { | |
color: black; | |
background-color: transparent; | |
text-decoration: none; | |
} | |
a:visited { | |
color: black; | |
background-color: transparent; | |
text-decoration: none; | |
} | |
a:hover { | |
color: black; | |
background-color: transparent; | |
text-decoration: underline; | |
} | |
a:active { | |
color: black; | |
background-color: transparent; | |
text-decoration: underline; | |
} | |
.mapboxgl-ctrl-geocoder { | |
border: 0; | |
border-radius: 0; | |
position: relative; | |
top: 0; | |
width: 800px; | |
margin-top: 0; | |
} | |
.mapboxgl-ctrl-geocoder > div { | |
min-width: 100%; | |
margin-left: 0; | |
} | |
</style> | |
<body> | |
<div class='sidebar'> | |
<div class='heading'> | |
<h1>Quiet Contractors</h1> | |
</div> | |
<div id='listings' class='listings'></div> | |
</div> | |
<div id='map' class='map pad2'> | |
</div> | |
<script> | |
if (!('remove' in Element.prototype)) { | |
Element.prototype.remove = function() { | |
if (this.parentNode) { | |
this.parentNode.removeChild(this); | |
} | |
}; | |
} | |
mapboxgl.accessToken = 'pk.eyJ1IjoiY2RpY2tpbnNvbjExIiwiYSI6ImNqY3J6eDlscTBweHMycXMwcWltbnRiN3MifQ.X68p3M-5wwH3AudbxEYdfw'; | |
var map = new mapboxgl.Map({ | |
container: 'map', | |
style: 'mapbox://styles/cdickinson11/cjg6j2hvr112u2rqgqfbdxpqg', | |
center: [-71.3039, 42.4259], | |
zoom: 8, | |
maxZoom: 11, | |
minZoom: 5, | |
cluster: true, | |
}); | |
var stores = 'MasterDirectory_QC_V10.geojson'; | |
map.on('load', function (e) { | |
map.addSource('places', { | |
type: 'geojson', | |
data: 'stores' | |
}); | |
buildLocationList(stores); | |
var geocoder = new MapboxGeocoder({ | |
accessToken: mapboxgl.accessToken, | |
bbox: [-124.848974, 24.396308 , -66.885444, 49.384358] | |
}); | |
map.addControl(geocoder, 'top-right'); | |
map.addSource('single-point', { | |
type: 'geojson', | |
data: { | |
type: 'FeatureCollection', | |
features: [] | |
} | |
}); | |
map.addLayer({ | |
id: 'point', | |
source: 'single-point', | |
type: 'circle', | |
paint: { | |
'circle-radius': 7, | |
'circle-color': '#00853e', | |
'circle-stroke-width': 3, | |
'circle-stroke-color': '#f2822d' | |
} | |
}); | |
geocoder.on('result', function(ev) { | |
var searchResult = ev.result.geometry; | |
map.getSource('single-point').setData(searchResult); | |
var options = { units: 'miles' }; | |
stores.features.forEach(function(store) { | |
Object.defineProperty(store.properties, 'distance', { | |
value: turf.distance(searchResult, store.geometry, options), | |
writable: true, | |
enumerable: true, | |
configurable: true | |
}); | |
stores.features.sort(function(a, b) { | |
if (a.properties.distance > b.properties.distance) { | |
return 1; | |
} | |
if (a.properties.distance < b.properties.distance) { | |
return -1; | |
} | |
return 0; | |
}); | |
var listings = document.getElementById('listings'); | |
while (listings.firstChild) { | |
listings.removeChild(listings.firstChild); | |
} | |
function sortLonLat(storeIdentifier) { | |
var lats = [stores.features[storeIdentifier].geometry.coordinates[1], searchResult.coordinates[1]]; | |
var lons = [stores.features[storeIdentifier].geometry.coordinates[0], searchResult.coordinates[0]]; | |
var sortedLons = lons.sort(function(a, b) { | |
if (a > b) { | |
return 1; | |
} | |
if (a.distance < b.distance) { | |
return -1; | |
} | |
return 0; | |
}); | |
var sortedLats = lats.sort(function(a, b) { | |
if (a > b) { | |
return 1; | |
} | |
if (a.distance < b.distance) { | |
return -1; | |
} | |
return 0; | |
}); | |
map.fitBounds([ | |
[sortedLons[0], sortedLats[0]], | |
[sortedLons[1], sortedLats[1]] | |
], { | |
padding: 100 | |
}); | |
} | |
sortLonLat(0); | |
createPopUp(stores.features[0]); | |
buildLocationList(stores); | |
}); | |
}); | |
}); | |
stores.features.forEach(function(marker, i) { | |
var el = document.createElement('div'); | |
el.id="marker-"+i; | |
el.className = 'marker'; | |
el.collision = 'true'; | |
new mapboxgl.Marker(el, { offset: [6, 15] }) | |
.setLngLat(marker.geometry.coordinates) | |
.addTo(map); | |
el.addEventListener('click', function(e) { | |
var activeItem = document.getElementsByClassName('active'); | |
flyToStore(marker); | |
createPopUp(marker); | |
e.stopPropagation(); | |
if (activeItem[0]) { | |
activeItem[0].classList.remove('active'); | |
} | |
var listing = document.getElementById('listing-' + i); | |
console.log(listing); | |
listing.classList.add('active'); | |
}); | |
}); | |
function flyToStore(currentFeature) { | |
map.flyTo({ | |
center: currentFeature.geometry.coordinates, | |
zoom: 11 | |
}); | |
} | |
function createPopUp(currentFeature) { | |
var popUps = document.getElementsByClassName('mapboxgl-popup'); | |
if (popUps[0]) popUps[0].remove(); | |
var popup = new mapboxgl.Popup({closeOnClick: false}) | |
.setLngLat(currentFeature.geometry.coordinates) | |
.setHTML('<h3><a href=' + currentFeature.properties.URL2 + '>' + currentFeature.properties.Company + '</a></h4>'+ ' · ' + currentFeature.properties.City + ", " + currentFeature.properties.State + '</p>' + ' · ' + "Phone: " + currentFeature.properties.Phone + '</p>') | |
.addTo(map); | |
} | |
function buildLocationList(data) { | |
for (i = 0; i < data.features.length; i++) { | |
var currentFeature = data.features[i]; | |
var prop = currentFeature.properties; | |
var listings = document.getElementById('listings'); | |
var listing = listings.appendChild(document.createElement('div')); | |
listing.className = 'item'; | |
listing.id = "listing-" + i; | |
var link = listing.appendChild(document.createElement('a')); | |
link.href = '#'; | |
link.className = 'title'; | |
link.dataPosition = i; | |
link.innerHTML = prop.Company; | |
var details = listing.appendChild(document.createElement('div')); | |
details.innerHTML = prop.City + ', ' + prop.State; | |
if (prop.Phone) { | |
details.innerHTML += ' · ' + prop.Phone; | |
} | |
if (prop.distance) { | |
var roundedDistance = Math.round(prop.distance * 100) / 100; | |
details.innerHTML += '<p><strong>' + roundedDistance + ' miles away</strong></p>'; | |
} | |
link.addEventListener('click', function(e) { | |
var clickedListing = data.features[this.dataPosition]; | |
flyToStore(clickedListing); | |
createPopUp(clickedListing); | |
var activeItem = document.getElementsByClassName('active'); | |
if (activeItem[0]) { | |
activeItem[0].classList.remove('active'); | |
} | |
this.parentNode.classList.add('active'); | |
}); | |
} | |
} | |
<\/script> | |
</body> | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment