Skip to content

Instantly share code, notes, and snippets.

@hcliff
Created June 14, 2017 22:19
Show Gist options
  • Save hcliff/32f50c8f7cc9cc8ce0a0689024037f87 to your computer and use it in GitHub Desktop.
Save hcliff/32f50c8f7cc9cc8ce0a0689024037f87 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title></title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.32.1/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.32.1/mapbox-gl.css' rel='stylesheet' />
<style id="jsbin-css">
html, body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
#map {
width: 100%;
height: calc(100% - 25px);
position:absolute;
top:25px;
}
#name-search{
float: left;
}
input {
box-sizing: border-box;
width:50%;
border: 0;
height: 25px;
padding: 0 5px;
}
#aggregates {
position: absolute;
top: 25px;
}
#tags {
margin: 0;
padding: 0;
display: block;
position: absolute;
bottom: 0;
max-height: 150px;
overflow: hidden;
}
#tags li {
display: inline-block;
margin: 2px 5px;
background: rgba(0,0,0,0.5);
padding: 3px 7px;
font-size: 12px;
font-family: verdana;
color: white;
border-radius: 6px;
}
li.active {
background: rgba(255,255,255,0.5);
color: black;
}
</style>
</head>
<body>
<input type="text" id="name-search" placeholder="search" />
<input type="datetime-local" id="start" />
<div id='map'></div>
<script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://cdn.jsdelivr.net/momentjs/2.14.1/moment-with-locales.min.js"></script>
<div id='aggregates'></div>
<ul id='tags'>venues: 30<ul>
<script id="jsbin-javascript">
mapboxgl.accessToken = 'pk.eyJ1IjoiY2FsZW5kcmUiLCJhIjoiY2lwMDk4NThhMDJpOHVmbTR6dWp3ZXIzbCJ9.QoQKozHFNWDVAiQy2c_AnQ';
const showVenues = true;
const showAggregates = true;
const showCache = true;
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
zoom: 20,
center: [-73.95185028352992, 40.711077039996724]
});
// const baseUrl = "https://pr-968.liveapp.com/";
const baseUrl = "http://localhost:3000/";
function getCallouts(value, start, finish, map, tagIds, venueId){
const bounds = map.getBounds();
const ne = bounds.getNorthEast().toArray();
const sw = bounds.getSouthWest().toArray();
var url = `${baseUrl}browse/callouts?clientVersion=${encodeURIComponent("consumer#1.0")}`;
if(value !== "" && value.length >= 3){
url += "&query="+value
}
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
start = moment(start);
finish = moment(finish);
url += `&events.occurrences.start=${start.format()}&events.occurrences.finish=${finish.format()}`
url += `&ne=${ne.join(",")}&sw=${sw.join(",")}`;
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
url += `&firstVenueId=${venueId}`;
url += `&limit=10`;
$.ajax(url, {
'success': function(response){
debugger;
const venue = response.items[0];
let html = `${venue.resolvedName}`;
if (venue.highlights && venue.highlights.length > 0){
html += '<ul>';
venue.highlights.forEach(function(highlight){
if(highlight.type === 'event'){
html += `<li>${highlight.item.name}</li>`;
}
});
html += '</ul>';
}
html += '<ul>';
response.items.slice(1).forEach(function(venue){
html += `<li>next: ${venue.resolvedName}`;
if (venue.highlights && venue.highlights.length > 0){
html += '<ul>';
venue.highlights.forEach(function(highlight){
if(highlight.type === 'event'){
html += `<li>${highlight.item.name}</li>`;
}
});
html += '</ul>';
}
html += '</li>';
});
html += '</ul>';
// Populate the popup and set its coordinates
// based on the feature found.
new mapboxgl.Popup()
.setLngLat([venue.geometry.coordinates[0], venue.geometry.coordinates[1]])
.setHTML(html)
.addTo(map);
}
})
}
function makeLegend(value, start, finish, map, tagIds){
const bounds = map.getBounds();
const ne = bounds.getNorthEast().toArray();
const sw = bounds.getSouthWest().toArray();
var url = `${baseUrl}browse/legend?clientVersion=${encodeURIComponent("consumer#1.0")}`
if(value !== "" && value.length >= 3){
url += "&query="+value
}
start = moment(start);
finish = moment(finish);
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
url += `&ne=${ne.join(",")}&sw=${sw.join(",")}`;
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
$.ajax(url, {
'success': function(response){
$('#tags').empty();
if (response.selectedTags) {
const selectedTags = response.selectedTags.items;
selectedTags.forEach(function(tag){
const li = $(`<li class="active">${tag.name}: ${tag.useCount || "-"}</li>`);
li.on("click", function(){
const inTagIds = _.indexOf(oldTagIds, tag.id) !== -1;
if(inTagIds){
oldTagIds = _.without(oldTagIds, tag.id);
$(li).removeClass('active');
}else{
oldTagIds.push(tag.id);
$(li).addClass('active');
}
swapSearch(oldQuery, oldStart, oldFinish, oldTagIds);
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
return $('#tags').append(li);
});
}
const tags = response.tags.items;
tags.forEach(function(tag){
const li = $(`<li>${tag.name}: ${tag.useCount}</li>`);
li.on("click", function(){
const inTagIds = _.indexOf(oldTagIds, tag.id) !== -1;
if(inTagIds){
oldTagIds = _.without(oldTagIds, tag.id);
$(li).removeClass('active');
}else{
oldTagIds.push(tag.id);
$(li).addClass('active');
}
swapSearch(oldQuery, oldStart, oldFinish, oldTagIds);
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
return $('#tags').append(li);
});
}
});
}
function makeAggregates(value, start, finish, map, tagIds){
const bounds = map.getBounds();
const ne = bounds.getNorthEast().toArray();
const sw = bounds.getSouthWest().toArray();
var url = `${baseUrl}browse/aggregates?clientVersion=${encodeURIComponent("consumer#1.0")}`
start = moment(start);
finish = moment(finish);
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
if(value !== "" && value.length >= 3){
url += "&query="+value
}
url += `&eventsOccurrencesStart=${start.toJSON()}&eventsOccurrencesFinish=${finish.toJSON()}`
url += `&ne=${ne.join(",")}&sw=${sw.join(",")}`;
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
$.ajax(url, {
'success': function(response){
$('#aggregates').html(`${response.venueCount} venues`);
}
});
}
function makeSearch(value, start, finish, tagIds){
var url = `${baseUrl}browse/tiles/{z}/{x}/{y}.pbf?clientVersion=${encodeURIComponent("consumer#1.0")}&debugTiles=true`
if(value !== "" && value.length >= 3){
url += "&query="+value
}
start = moment(start).startOf('hour');
finish = moment(finish).startOf('hour');
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
url += `&aggregateThreshold=100`
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
map.addSource("live-venues", {
type: 'vector',
"tiles": [url]
});
const genreColors = {
property: 'genre',
type: 'categorical',
stops: [
['misc', '#22364D'],
['municipal', '#737780'],
['service', '#A3846A'],
['none', '#FFFFFF'],
['lodging', '#C2574E'],
['body', '#F77CC6'],
['homeAndHobby', '#FF8F33'],
['activity', '#4CCF78'],
['groups', '#9BC2A2'],
['food', '#17C2E8'],
['essentials', '#3D87FF'],
['drinks', '#772EE6'],
['style', '#FABF0F']
]
};
const circleRadius = {
"base": 1,
"stops": [
[5, 1],
[8, 1],
[9, 1.25],
[11, 1.5],
[12, 2],
[13, 2],
[14, 2],
[15, 2],
[16, 2.5],
[17, 2.8],
[18, 3],
[19, 3.5],
[20, 4],
[21, 5]
]
};
if(showAggregates){
map.addLayer({
"id": "aggregate-dots-layer",
"type": "circle",
"source": "live-venues",
"source-layer": "aggregates",
"paint": {
"circle-radius": circleRadius,
'circle-stroke-width': {
property: 'hasEvent',
stops: [
[0, 0],
[1, 2]
]
},
'circle-stroke-color': '#000000',
'circle-color': '#ff0000',
'circle-color': genreColors
}
});
}
map.addLayer({
"id": "debugTiles",
"type": "line",
"source": "live-venues",
"source-layer": "debugTiles",
"layout": {},
'paint': {
'line-color': '#ff0000',
'line-opacity': 0.8,
'line-width': 3
}
});
if(showCache){
map.addLayer({
"id": "skinnyVenues",
"type": "circle",
"source": "live-venues",
"source-layer": "skinnyVenues",
"layout": {},
"paint": {
"circle-color": genreColors,
"circle-radius": circleRadius
}
});
}
// map.addLayer({
// "id": "geohashDebug",
// "type": "line",
// "source": "live-venues",
// "source-layer": "aggregatesDebug",
// "layout": {},
// 'paint': {
// 'line-color': '#000000',
// 'line-opacity': 0.2,
// 'line-width': 1
// }
// });
if(showVenues){
// map.addLayer({
// "id": "venue-labels-layer",
// "type": "symbol",
// "source": "live-venues",
// "source-layer": "venues",
// "layout": {
// "text-field": "{name}",
// "text-size": 14,
// "text-offset": [0, -1],
// "text-max-width": 15
// }
// });
map.addLayer({
"id": "venue-dots-layer",
"type": "circle",
"source": "live-venues",
"source-layer": "venues",
'paint': {
'circle-radius': circleRadius,
'circle-stroke-width': {
property: 'hasEvent',
stops: [
[0, 0],
[1, 2]
]
},
'circle-stroke-color': '#000000',
'circle-color': genreColors
}
});
}
}
function swapSearch(value, start, finish, tagIds){
map.removeSource('live-venues');
map.removeLayer('venue-labels-layer');
map.removeLayer('venue-dots-layer');
makeSearch(value, start, finish, tagIds);
}
Date.prototype.toDateInputValue = (function() {
var local = new Date(this);
local.setMinutes(this.getMinutes() - this.getTimezoneOffset());
return local.toJSON().slice(0,16);
});
var oldQuery = "";
var oldStart = new Date();
var oldFinish = new Date(oldStart);
oldFinish.setMinutes(oldFinish.getMinutes() + 180);
var oldTagIds = [];
document.addEventListener('DOMContentLoaded', function(){
var search = document.getElementById("name-search");
search.addEventListener('keyup', function(){
if(search.value.length < 3 && oldQuery.length < 3){
return
}
swapSearch(search.value, oldStart, oldFinish, oldTagIds);
makeLegend(search.value, oldStart, oldFinish, map, oldTagIds);
makeAggregates(search.value, oldStart, oldFinish, map, oldTagIds);
oldQuery = search.value;
});
var startInput = document.getElementById("start");
start.value = oldStart.toDateInputValue();
startInput.addEventListener('keyup', function(){
let start = new Date(startInput.value);
let finish = new Date(startInput.value);
finish.setMinutes(finish.getMinutes() + 90);
swapSearch(oldQuery, start, finish, oldTagIds);
makeLegend(oldQuery, start, finish, map, oldTagIds);
makeAggregates(oldQuery, start, finish, map, oldTagIds);
oldStart = start;
oldFinish = finish;
});
map.on('load', function () {
makeSearch(oldQuery, oldStart, oldFinish, oldTagIds);
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
makeAggregates(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
map.on('moveend', function() {
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
makeAggregates(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
map.on('click', function (e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['venue-dots-layer'] });
if (!features.length) {
return;
}
// console.log("features", features);
features.map(function(feature){
console.log("feature", feature.properties);
})
var feature = features[0];
getCallouts(oldQuery, oldStart, oldFinish, map, oldTagIds, feature.properties.id);
});
});
map.addControl(new mapboxgl.NavigationControl());
window.map = map;
window.parent.map = map;
</script>
<script id="jsbin-source-css" type="text/css">html, body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
#map {
width: 100%;
height: calc(100% - 25px);
position:absolute;
top:25px;
}
#name-search{
float: left;
}
input {
box-sizing: border-box;
width:50%;
border: 0;
height: 25px;
padding: 0 5px;
}
#aggregates {
position: absolute;
top: 25px;
}
#tags {
margin: 0;
padding: 0;
display: block;
position: absolute;
bottom: 0;
max-height: 150px;
overflow: hidden;
}
#tags li {
display: inline-block;
margin: 2px 5px;
background: rgba(0,0,0,0.5);
padding: 3px 7px;
font-size: 12px;
font-family: verdana;
color: white;
border-radius: 6px;
}
li.active {
background: rgba(255,255,255,0.5);
color: black;
}</script>
<script id="jsbin-source-javascript" type="text/javascript">mapboxgl.accessToken = 'pk.eyJ1IjoiY2FsZW5kcmUiLCJhIjoiY2lwMDk4NThhMDJpOHVmbTR6dWp3ZXIzbCJ9.QoQKozHFNWDVAiQy2c_AnQ';
const showVenues = true;
const showAggregates = true;
const showCache = true;
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
zoom: 20,
center: [-73.95185028352992, 40.711077039996724]
});
// const baseUrl = "https://pr-968.liveapp.com/";
const baseUrl = "http://localhost:3000/";
function getCallouts(value, start, finish, map, tagIds, venueId){
const bounds = map.getBounds();
const ne = bounds.getNorthEast().toArray();
const sw = bounds.getSouthWest().toArray();
var url = `${baseUrl}browse/callouts?clientVersion=${encodeURIComponent("consumer#1.0")}`;
if(value !== "" && value.length >= 3){
url += "&query="+value
}
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
start = moment(start);
finish = moment(finish);
url += `&events.occurrences.start=${start.format()}&events.occurrences.finish=${finish.format()}`
url += `&ne=${ne.join(",")}&sw=${sw.join(",")}`;
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
url += `&firstVenueId=${venueId}`;
url += `&limit=10`;
$.ajax(url, {
'success': function(response){
debugger;
const venue = response.items[0];
let html = `${venue.resolvedName}`;
if (venue.highlights && venue.highlights.length > 0){
html += '<ul>';
venue.highlights.forEach(function(highlight){
if(highlight.type === 'event'){
html += `<li>${highlight.item.name}</li>`;
}
});
html += '</ul>';
}
html += '<ul>';
response.items.slice(1).forEach(function(venue){
html += `<li>next: ${venue.resolvedName}`;
if (venue.highlights && venue.highlights.length > 0){
html += '<ul>';
venue.highlights.forEach(function(highlight){
if(highlight.type === 'event'){
html += `<li>${highlight.item.name}</li>`;
}
});
html += '</ul>';
}
html += '</li>';
});
html += '</ul>';
// Populate the popup and set its coordinates
// based on the feature found.
new mapboxgl.Popup()
.setLngLat([venue.geometry.coordinates[0], venue.geometry.coordinates[1]])
.setHTML(html)
.addTo(map);
}
})
}
function makeLegend(value, start, finish, map, tagIds){
const bounds = map.getBounds();
const ne = bounds.getNorthEast().toArray();
const sw = bounds.getSouthWest().toArray();
var url = `${baseUrl}browse/legend?clientVersion=${encodeURIComponent("consumer#1.0")}`
if(value !== "" && value.length >= 3){
url += "&query="+value
}
start = moment(start);
finish = moment(finish);
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
url += `&ne=${ne.join(",")}&sw=${sw.join(",")}`;
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
$.ajax(url, {
'success': function(response){
$('#tags').empty();
if (response.selectedTags) {
const selectedTags = response.selectedTags.items;
selectedTags.forEach(function(tag){
const li = $(`<li class="active">${tag.name}: ${tag.useCount || "-"}</li>`);
li.on("click", function(){
const inTagIds = _.indexOf(oldTagIds, tag.id) !== -1;
if(inTagIds){
oldTagIds = _.without(oldTagIds, tag.id);
$(li).removeClass('active');
}else{
oldTagIds.push(tag.id);
$(li).addClass('active');
}
swapSearch(oldQuery, oldStart, oldFinish, oldTagIds);
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
return $('#tags').append(li);
});
}
const tags = response.tags.items;
tags.forEach(function(tag){
const li = $(`<li>${tag.name}: ${tag.useCount}</li>`);
li.on("click", function(){
const inTagIds = _.indexOf(oldTagIds, tag.id) !== -1;
if(inTagIds){
oldTagIds = _.without(oldTagIds, tag.id);
$(li).removeClass('active');
}else{
oldTagIds.push(tag.id);
$(li).addClass('active');
}
swapSearch(oldQuery, oldStart, oldFinish, oldTagIds);
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
return $('#tags').append(li);
});
}
});
}
function makeAggregates(value, start, finish, map, tagIds){
const bounds = map.getBounds();
const ne = bounds.getNorthEast().toArray();
const sw = bounds.getSouthWest().toArray();
var url = `${baseUrl}browse/aggregates?clientVersion=${encodeURIComponent("consumer#1.0")}`
start = moment(start);
finish = moment(finish);
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
if(value !== "" && value.length >= 3){
url += "&query="+value
}
url += `&eventsOccurrencesStart=${start.toJSON()}&eventsOccurrencesFinish=${finish.toJSON()}`
url += `&ne=${ne.join(",")}&sw=${sw.join(",")}`;
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
$.ajax(url, {
'success': function(response){
$('#aggregates').html(`${response.venueCount} venues`);
}
});
}
function makeSearch(value, start, finish, tagIds){
var url = `${baseUrl}browse/tiles/{z}/{x}/{y}.pbf?clientVersion=${encodeURIComponent("consumer#1.0")}&debugTiles=true`
if(value !== "" && value.length >= 3){
url += "&query="+value
}
start = moment(start).startOf('hour');
finish = moment(finish).startOf('hour');
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
url += `&aggregateThreshold=100`
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
map.addSource("live-venues", {
type: 'vector',
"tiles": [url]
});
const genreColors = {
property: 'genre',
type: 'categorical',
stops: [
['misc', '#22364D'],
['municipal', '#737780'],
['service', '#A3846A'],
['none', '#FFFFFF'],
['lodging', '#C2574E'],
['body', '#F77CC6'],
['homeAndHobby', '#FF8F33'],
['activity', '#4CCF78'],
['groups', '#9BC2A2'],
['food', '#17C2E8'],
['essentials', '#3D87FF'],
['drinks', '#772EE6'],
['style', '#FABF0F']
]
};
const circleRadius = {
"base": 1,
"stops": [
[5, 1],
[8, 1],
[9, 1.25],
[11, 1.5],
[12, 2],
[13, 2],
[14, 2],
[15, 2],
[16, 2.5],
[17, 2.8],
[18, 3],
[19, 3.5],
[20, 4],
[21, 5]
]
};
if(showAggregates){
map.addLayer({
"id": "aggregate-dots-layer",
"type": "circle",
"source": "live-venues",
"source-layer": "aggregates",
"paint": {
"circle-radius": circleRadius,
'circle-stroke-width': {
property: 'hasEvent',
stops: [
[0, 0],
[1, 2]
]
},
'circle-stroke-color': '#000000',
'circle-color': '#ff0000',
'circle-color': genreColors
}
});
}
map.addLayer({
"id": "debugTiles",
"type": "line",
"source": "live-venues",
"source-layer": "debugTiles",
"layout": {},
'paint': {
'line-color': '#ff0000',
'line-opacity': 0.8,
'line-width': 3
}
});
if(showCache){
map.addLayer({
"id": "skinnyVenues",
"type": "circle",
"source": "live-venues",
"source-layer": "skinnyVenues",
"layout": {},
"paint": {
"circle-color": genreColors,
"circle-radius": circleRadius
}
});
}
// map.addLayer({
// "id": "geohashDebug",
// "type": "line",
// "source": "live-venues",
// "source-layer": "aggregatesDebug",
// "layout": {},
// 'paint': {
// 'line-color': '#000000',
// 'line-opacity': 0.2,
// 'line-width': 1
// }
// });
if(showVenues){
// map.addLayer({
// "id": "venue-labels-layer",
// "type": "symbol",
// "source": "live-venues",
// "source-layer": "venues",
// "layout": {
// "text-field": "{name}",
// "text-size": 14,
// "text-offset": [0, -1],
// "text-max-width": 15
// }
// });
map.addLayer({
"id": "venue-dots-layer",
"type": "circle",
"source": "live-venues",
"source-layer": "venues",
'paint': {
'circle-radius': circleRadius,
'circle-stroke-width': {
property: 'hasEvent',
stops: [
[0, 0],
[1, 2]
]
},
'circle-stroke-color': '#000000',
'circle-color': genreColors
}
});
}
}
function swapSearch(value, start, finish, tagIds){
map.removeSource('live-venues');
map.removeLayer('venue-labels-layer');
map.removeLayer('venue-dots-layer');
makeSearch(value, start, finish, tagIds);
}
Date.prototype.toDateInputValue = (function() {
var local = new Date(this);
local.setMinutes(this.getMinutes() - this.getTimezoneOffset());
return local.toJSON().slice(0,16);
});
var oldQuery = "";
var oldStart = new Date();
var oldFinish = new Date(oldStart);
oldFinish.setMinutes(oldFinish.getMinutes() + 180);
var oldTagIds = [];
document.addEventListener('DOMContentLoaded', function(){
var search = document.getElementById("name-search");
search.addEventListener('keyup', function(){
if(search.value.length < 3 && oldQuery.length < 3){
return
}
swapSearch(search.value, oldStart, oldFinish, oldTagIds);
makeLegend(search.value, oldStart, oldFinish, map, oldTagIds);
makeAggregates(search.value, oldStart, oldFinish, map, oldTagIds);
oldQuery = search.value;
});
var startInput = document.getElementById("start");
start.value = oldStart.toDateInputValue();
startInput.addEventListener('keyup', function(){
let start = new Date(startInput.value);
let finish = new Date(startInput.value);
finish.setMinutes(finish.getMinutes() + 90);
swapSearch(oldQuery, start, finish, oldTagIds);
makeLegend(oldQuery, start, finish, map, oldTagIds);
makeAggregates(oldQuery, start, finish, map, oldTagIds);
oldStart = start;
oldFinish = finish;
});
map.on('load', function () {
makeSearch(oldQuery, oldStart, oldFinish, oldTagIds);
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
makeAggregates(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
map.on('moveend', function() {
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
makeAggregates(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
map.on('click', function (e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['venue-dots-layer'] });
if (!features.length) {
return;
}
// console.log("features", features);
features.map(function(feature){
console.log("feature", feature.properties);
})
var feature = features[0];
getCallouts(oldQuery, oldStart, oldFinish, map, oldTagIds, feature.properties.id);
});
});
map.addControl(new mapboxgl.NavigationControl());
window.map = map;
window.parent.map = map;</script></body>
</html>
html, body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
#map {
width: 100%;
height: calc(100% - 25px);
position:absolute;
top:25px;
}
#name-search{
float: left;
}
input {
box-sizing: border-box;
width:50%;
border: 0;
height: 25px;
padding: 0 5px;
}
#aggregates {
position: absolute;
top: 25px;
}
#tags {
margin: 0;
padding: 0;
display: block;
position: absolute;
bottom: 0;
max-height: 150px;
overflow: hidden;
}
#tags li {
display: inline-block;
margin: 2px 5px;
background: rgba(0,0,0,0.5);
padding: 3px 7px;
font-size: 12px;
font-family: verdana;
color: white;
border-radius: 6px;
}
li.active {
background: rgba(255,255,255,0.5);
color: black;
}
mapboxgl.accessToken = 'pk.eyJ1IjoiY2FsZW5kcmUiLCJhIjoiY2lwMDk4NThhMDJpOHVmbTR6dWp3ZXIzbCJ9.QoQKozHFNWDVAiQy2c_AnQ';
const showVenues = true;
const showAggregates = true;
const showCache = true;
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
zoom: 20,
center: [-73.95185028352992, 40.711077039996724]
});
// const baseUrl = "https://pr-968.liveapp.com/";
const baseUrl = "http://localhost:3000/";
function getCallouts(value, start, finish, map, tagIds, venueId){
const bounds = map.getBounds();
const ne = bounds.getNorthEast().toArray();
const sw = bounds.getSouthWest().toArray();
var url = `${baseUrl}browse/callouts?clientVersion=${encodeURIComponent("consumer#1.0")}`;
if(value !== "" && value.length >= 3){
url += "&query="+value
}
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
start = moment(start);
finish = moment(finish);
url += `&events.occurrences.start=${start.format()}&events.occurrences.finish=${finish.format()}`
url += `&ne=${ne.join(",")}&sw=${sw.join(",")}`;
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
url += `&firstVenueId=${venueId}`;
url += `&limit=10`;
$.ajax(url, {
'success': function(response){
debugger;
const venue = response.items[0];
let html = `${venue.resolvedName}`;
if (venue.highlights && venue.highlights.length > 0){
html += '<ul>';
venue.highlights.forEach(function(highlight){
if(highlight.type === 'event'){
html += `<li>${highlight.item.name}</li>`;
}
});
html += '</ul>';
}
html += '<ul>';
response.items.slice(1).forEach(function(venue){
html += `<li>next: ${venue.resolvedName}`;
if (venue.highlights && venue.highlights.length > 0){
html += '<ul>';
venue.highlights.forEach(function(highlight){
if(highlight.type === 'event'){
html += `<li>${highlight.item.name}</li>`;
}
});
html += '</ul>';
}
html += '</li>';
});
html += '</ul>';
// Populate the popup and set its coordinates
// based on the feature found.
new mapboxgl.Popup()
.setLngLat([venue.geometry.coordinates[0], venue.geometry.coordinates[1]])
.setHTML(html)
.addTo(map);
}
})
}
function makeLegend(value, start, finish, map, tagIds){
const bounds = map.getBounds();
const ne = bounds.getNorthEast().toArray();
const sw = bounds.getSouthWest().toArray();
var url = `${baseUrl}browse/legend?clientVersion=${encodeURIComponent("consumer#1.0")}`
if(value !== "" && value.length >= 3){
url += "&query="+value
}
start = moment(start);
finish = moment(finish);
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
url += `&ne=${ne.join(",")}&sw=${sw.join(",")}`;
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
$.ajax(url, {
'success': function(response){
$('#tags').empty();
if (response.selectedTags) {
const selectedTags = response.selectedTags.items;
selectedTags.forEach(function(tag){
const li = $(`<li class="active">${tag.name}: ${tag.useCount || "-"}</li>`);
li.on("click", function(){
const inTagIds = _.indexOf(oldTagIds, tag.id) !== -1;
if(inTagIds){
oldTagIds = _.without(oldTagIds, tag.id);
$(li).removeClass('active');
}else{
oldTagIds.push(tag.id);
$(li).addClass('active');
}
swapSearch(oldQuery, oldStart, oldFinish, oldTagIds);
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
return $('#tags').append(li);
});
}
const tags = response.tags.items;
tags.forEach(function(tag){
const li = $(`<li>${tag.name}: ${tag.useCount}</li>`);
li.on("click", function(){
const inTagIds = _.indexOf(oldTagIds, tag.id) !== -1;
if(inTagIds){
oldTagIds = _.without(oldTagIds, tag.id);
$(li).removeClass('active');
}else{
oldTagIds.push(tag.id);
$(li).addClass('active');
}
swapSearch(oldQuery, oldStart, oldFinish, oldTagIds);
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
return $('#tags').append(li);
});
}
});
}
function makeAggregates(value, start, finish, map, tagIds){
const bounds = map.getBounds();
const ne = bounds.getNorthEast().toArray();
const sw = bounds.getSouthWest().toArray();
var url = `${baseUrl}browse/aggregates?clientVersion=${encodeURIComponent("consumer#1.0")}`
start = moment(start);
finish = moment(finish);
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
if(value !== "" && value.length >= 3){
url += "&query="+value
}
url += `&eventsOccurrencesStart=${start.toJSON()}&eventsOccurrencesFinish=${finish.toJSON()}`
url += `&ne=${ne.join(",")}&sw=${sw.join(",")}`;
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
$.ajax(url, {
'success': function(response){
$('#aggregates').html(`${response.venueCount} venues`);
}
});
}
function makeSearch(value, start, finish, tagIds){
var url = `${baseUrl}browse/tiles/{z}/{x}/{y}.pbf?clientVersion=${encodeURIComponent("consumer#1.0")}&debugTiles=true`
if(value !== "" && value.length >= 3){
url += "&query="+value
}
start = moment(start).startOf('hour');
finish = moment(finish).startOf('hour');
url += `&highlights.start=${start.format()}&highlights.finish=${finish.format()}`
url += `&aggregateThreshold=100`
tagIds.forEach(function(tagId){
url += `&tagIds=${tagId}`;
});
map.addSource("live-venues", {
type: 'vector',
"tiles": [url]
});
const genreColors = {
property: 'genre',
type: 'categorical',
stops: [
['misc', '#22364D'],
['municipal', '#737780'],
['service', '#A3846A'],
['none', '#FFFFFF'],
['lodging', '#C2574E'],
['body', '#F77CC6'],
['homeAndHobby', '#FF8F33'],
['activity', '#4CCF78'],
['groups', '#9BC2A2'],
['food', '#17C2E8'],
['essentials', '#3D87FF'],
['drinks', '#772EE6'],
['style', '#FABF0F']
]
};
const circleRadius = {
"base": 1,
"stops": [
[5, 1],
[8, 1],
[9, 1.25],
[11, 1.5],
[12, 2],
[13, 2],
[14, 2],
[15, 2],
[16, 2.5],
[17, 2.8],
[18, 3],
[19, 3.5],
[20, 4],
[21, 5]
]
};
if(showAggregates){
map.addLayer({
"id": "aggregate-dots-layer",
"type": "circle",
"source": "live-venues",
"source-layer": "aggregates",
"paint": {
"circle-radius": circleRadius,
'circle-stroke-width': {
property: 'hasEvent',
stops: [
[0, 0],
[1, 2]
]
},
'circle-stroke-color': '#000000',
'circle-color': '#ff0000',
'circle-color': genreColors
}
});
}
map.addLayer({
"id": "debugTiles",
"type": "line",
"source": "live-venues",
"source-layer": "debugTiles",
"layout": {},
'paint': {
'line-color': '#ff0000',
'line-opacity': 0.8,
'line-width': 3
}
});
if(showCache){
map.addLayer({
"id": "skinnyVenues",
"type": "circle",
"source": "live-venues",
"source-layer": "skinnyVenues",
"layout": {},
"paint": {
"circle-color": genreColors,
"circle-radius": circleRadius
}
});
}
// map.addLayer({
// "id": "geohashDebug",
// "type": "line",
// "source": "live-venues",
// "source-layer": "aggregatesDebug",
// "layout": {},
// 'paint': {
// 'line-color': '#000000',
// 'line-opacity': 0.2,
// 'line-width': 1
// }
// });
if(showVenues){
// map.addLayer({
// "id": "venue-labels-layer",
// "type": "symbol",
// "source": "live-venues",
// "source-layer": "venues",
// "layout": {
// "text-field": "{name}",
// "text-size": 14,
// "text-offset": [0, -1],
// "text-max-width": 15
// }
// });
map.addLayer({
"id": "venue-dots-layer",
"type": "circle",
"source": "live-venues",
"source-layer": "venues",
'paint': {
'circle-radius': circleRadius,
'circle-stroke-width': {
property: 'hasEvent',
stops: [
[0, 0],
[1, 2]
]
},
'circle-stroke-color': '#000000',
'circle-color': genreColors
}
});
}
}
function swapSearch(value, start, finish, tagIds){
map.removeSource('live-venues');
map.removeLayer('venue-labels-layer');
map.removeLayer('venue-dots-layer');
makeSearch(value, start, finish, tagIds);
}
Date.prototype.toDateInputValue = (function() {
var local = new Date(this);
local.setMinutes(this.getMinutes() - this.getTimezoneOffset());
return local.toJSON().slice(0,16);
});
var oldQuery = "";
var oldStart = new Date();
var oldFinish = new Date(oldStart);
oldFinish.setMinutes(oldFinish.getMinutes() + 180);
var oldTagIds = [];
document.addEventListener('DOMContentLoaded', function(){
var search = document.getElementById("name-search");
search.addEventListener('keyup', function(){
if(search.value.length < 3 && oldQuery.length < 3){
return
}
swapSearch(search.value, oldStart, oldFinish, oldTagIds);
makeLegend(search.value, oldStart, oldFinish, map, oldTagIds);
makeAggregates(search.value, oldStart, oldFinish, map, oldTagIds);
oldQuery = search.value;
});
var startInput = document.getElementById("start");
start.value = oldStart.toDateInputValue();
startInput.addEventListener('keyup', function(){
let start = new Date(startInput.value);
let finish = new Date(startInput.value);
finish.setMinutes(finish.getMinutes() + 90);
swapSearch(oldQuery, start, finish, oldTagIds);
makeLegend(oldQuery, start, finish, map, oldTagIds);
makeAggregates(oldQuery, start, finish, map, oldTagIds);
oldStart = start;
oldFinish = finish;
});
map.on('load', function () {
makeSearch(oldQuery, oldStart, oldFinish, oldTagIds);
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
makeAggregates(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
map.on('moveend', function() {
makeLegend(oldQuery, oldStart, oldFinish, map, oldTagIds);
makeAggregates(oldQuery, oldStart, oldFinish, map, oldTagIds);
});
map.on('click', function (e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['venue-dots-layer'] });
if (!features.length) {
return;
}
// console.log("features", features);
features.map(function(feature){
console.log("feature", feature.properties);
})
var feature = features[0];
getCallouts(oldQuery, oldStart, oldFinish, map, oldTagIds, feature.properties.id);
});
});
map.addControl(new mapboxgl.NavigationControl());
window.map = map;
window.parent.map = map;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment