Skip to content

Instantly share code, notes, and snippets.

@femtope
Forked from clhenrick/index.html
Created October 13, 2016 10:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save femtope/9d94e9f92bfab2bd96e9c9e704c36f5f to your computer and use it in GitHub Desktop.
Save femtope/9d94e9f92bfab2bd96e9c9e704c36f5f to your computer and use it in GitHub Desktop.
cartodb.js set sublayer interactivity
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Northwest Bushwick Community Map</title>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.css" />
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.0/themes/base/jquery-ui.css">
<!-- <link rel="stylesheet" href="css/style.css" type="text/css" /> -->
<link rel="stylesheet" type="text/css" href="css/styles-new.css">
</head>
<body>
<div id="menu"></div>
<div id="intro">
<h1>Northwest Bushwick Community Map</h1>
<p>The Bushwick Community Map is a mapping project that will provide local residents and community organizers with housing and urban planning data of our neighborhood to help track the changes happening in Bushwick, particularly the urban vices of gentrification and displacement.</p>
</div>
<input type="text" placeholder="Search for a Bushwick address" id="search-box" class="ui"/>
<input type="button" id="search-button" />
<div id="ui-container" class="ui">
<h4>Property Layers</h4><br/>
<a href="#regular" id="regular" class="button">All Tax Lots</a>
<a href="#availfar" id="availfar" class="button">Available FAR</a>
<a href="#rentstab" id="rentstab" class="button">Likely Rent Stabilized</a>
<a href="#zoning" id="zoning" class="button">Zoning</a>
<a href="#vacant" id="vacant" class="button">Vacant Land</a>
<hr/>
<h4>DOB Permits</h4><br/>
<input type="checkbox" name="dob" class="regular-checkbox dob" value="a1" id="a1" />
<label for="a1"></label>A1: Major Alteration<br/>
<input type="checkbox" name="dob" class="regular-checkbox dob" value="a2a3" id="a2a3" />
<label for="a2a3"></label>A2, A3: Minor Alteration<br/>
<input type="checkbox" name="dob" class="regular-checkbox dob" value="new-buildings" id="nb"/>
<label for="nb"></label>New Buildings
<hr/>
<h4>Stories</h4><br/>
<input type="checkbox" name="stories" class="regular-checkbox" value="sites-of-gentrification" id="sites-of-gentrification"/>
<label for="sites-of-gentrification"></label>Sites of Gentrification<br/>
<input type="checkbox" name="stories" class="regular-checkbox" value="personal-stories" id="personal-stories"/>
<label for="personal-stories"></label>Personal Stories
</div>
<div id="history" class="ui">
<h4>Year Built</h4>
<div id="slider-container">
<div id="slider-range"></div>
<p class="year" id="year-min"></p>
<p class="year" id="year-max"></p>
</div>
</div>
<div id="map"></div>
<!-- libraries -->
<script src="http://libs.cartocdn.com/cartodb.js/v3/cartodb.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.0/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://maps.stamen.com/js/tile.stamen.js?v1.2.3"></script>
<!-- plugins -->
<script src="http://maps.google.com/maps/api/js?v=3&sensor=false"></script>
<!-- data -->
<!-- <script src='data/bushwick14v1_edited.js'></script>
<script src='data/exp_CodedJobs.js'></script> -->
<script type="infowindow/html" id="infowindow_template">
<div class="cartodb-popup">
<a href="#close" class="cartodb-popup-close-button close">x</a>
<div class="cartodb-popup-content-wrapper">
<div class="cartodb-popup-header">
<img style="width: 100%" src="http://cartodb.com/assets/logos/logos_full_cartodb_light.png"></src>
</div>
<div class="cartodb-popup-content">
<!-- //content.data contains the field info -->
<h4>Address: </h4>
<p>{{content.data.address}}</p>
</div>
</div>
<div class="cartodb-popup-tip-container"></div>
</div>
</script>
<script src="js/timerange_ui.js"></script>
<script src="js/mapStyles.js"></script>
<script src="js/main.js"></script>
<!--
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-53968131-1', 'auto');
ga('send', 'pageview');
</script>
-->
</body>
</html>
/*** Global object that contains the app ***/
var app = app || {};
// keep our map stuff in a part of the app object as to not pollute the global name space
app.map = (function(w,d, $, _){
/*** local variables for map parts and layers ***/
var el = {
map : null,
cdbURL : null,
styles: null,
sql : null,
tonerLite : null,
satellite : null,
taxLots : null,
dobPermits : null,
dobPermitsA1 : null,
dobPermitsA2A3 : null,
dobPermitsNB : null
};
// reference cartocss styles from mapStyles.js
el.styles = app.mapStyles;
// url to cartodb bushwick community map viz json
el.cdbURL = "http://bushwick.cartodb.com/api/v2/viz/64ceb582-71e2-11e4-b052-0e018d66dc29/viz.json";
// queries for map pluto tax lots
// sent to cartodb when layer buttons clicked
el.sql = {
all : "SELECT * FROM bushwick_pluto14v1",
rentStab : "SELECT * FROM bushwick_pluto14v1 WHERE yearbuilt < 1974 AND unitsres > 6",
vacant : "SELECT * FROM bushwick_pluto14v1 WHERE landuse = '11'",
};
// set up the map
var initMap = function() {
// map paramaters
var params = {
center : [40.6941, -73.9162],
minZoom : 14,
maxZoom : 20,
zoom : 15,
maxBounds : L.latLngBounds([40.670809,-73.952579],[40.713565,-73.870354]),
cartodb_logo: false,
legends: false
}
// instantiate the Leaflet map
// el.map = L.map('map', params);
// el.tonerLite = new L.StamenTileLayer('toner-lite');
// add stamen toner layer as default base layer
// el.map.addLayer(el.tonerLite);
// add the tax lot layer from cartodb
getCDBData(params);
}
// function to load map pluto tax lot layer and dob permit layer
// from CartoDB
var getCDBData = function(mapOptions) {
cartodb.createVis('map', el.cdbURL, mapOptions, {
cartodb_logo: false,
legends: false
},
function(vis, layers) {
// store the map pluto tax lot sublayer
layer = layers[1];
// layer.getSubLayer(0).setCartoCSS(el.styles.regular);
//layer.getSubLayer(0).setSQL(el.sql.all);
el.taxLots = layer.getSubLayer(0);
// store the dob permits a1 sublayer
el.dobPermitsA1 = layer.createSubLayer({
sql : "SELECT * FROM exp_codedjobs_a1",
cartocss : '#exp_codedjobs_a1 {marker-width: 7; marker-fill: hsl(0,0%,35%); marker-line-color: white; marker-line-width: 0;}',
interactivity: ['address']
});
// store the dob permits a2a3 sublayer
el.dobPermitsA2A3 = layer.createSubLayer({
sql : "SELECT * FROM exp_codedjobs_a2a3",
cartocss : '#exp_codedjobs_a1 {marker-width: 7; marker-fill: hsl(100,0%,60%); marker-line-color: white; marker-line-width: 0;}',
interactivity: 'address'
});
// store the dob permits nb sublayer
el.dobPermitsNB = layer.createSubLayer({
sql : "SELECT * FROM exp_codedjobs_nb",
cartocss : '#exp_codedjobs_a1 {marker-width: 7; marker-fill: hsl(350,0%,10%); marker-line-color: white; marker-line-width: 0;}',
interactivity: 'address'
});
var event = function(e){
$('#tool-tip').css({
left: e.pageX,
top: e.pageY
});
};
// vis.addOverlay({
// type: 'tooltip',
// position : 'top|center',
// template : '<p>{{address}}</p>'
// });
// hide sublayers for dob permits
var num_sublayers = layer.getSubLayerCount();
for (var i = 1; i < num_sublayers; i++) {
//console.log('sublayers: ', layer.getSubLayer(i));
layer.getSubLayer(i).setInteraction(true);
layer.getSubLayer(i).infowindow.set('template', $('#infowindow_template').html())
.on('error', function(err){
console.log('infowindow error: ', err);
});
layer.getSubLayer(i).on('featureOver', function(e,pos,latlng,data){
$('#tool-tip').html('<p>' + data.address + '</p>');
$(document).bind('mousemove', event);
$('#tool-tip').show();
});
layer.getSubLayer(i).on('featureOut', function(e,pos,latlng,data){
//Make the tooltip go away when off cities
$('#tool-tip').hide();
$(document).unbind('mousemove', event, false);
});
layer.getSubLayer(i).hide();
}
});//.addTo(el.map);
};
// change the cartoCSS of a layer
var changeCartoCSS = function(layer, css) {
layer.setCartoCSS(css);
};
// change SQL query of a layer
var changeSQL = function(layer, sql) {
layer.setSQL(sql);
}
// corresponding cartoCSS changes to tax lot layer buttons
var taxLotActions = {
regular : function() {
changeCartoCSS(el.taxLots, el.styles.regular);
changeSQL(el.taxLots, el.sql.all);
return true;
},
zoning : function() {
changeCartoCSS(el.taxLots, el.styles.zoning);
changeSQL(el.taxLots, el.sql.all);
return true;
},
availfar : function() {
changeCartoCSS(el.taxLots, el.styles.availFAR);
changeSQL(el.taxLots, el.sql.all);
return true;
},
rentstab : function() {
changeCartoCSS(el.taxLots, el.styles.red);
changeSQL(el.taxLots, el.sql.rentStab);
return true;
},
vacant : function() {
changeCartoCSS(el.taxLots, el.styles.red);
changeSQL(el.taxLots, el.sql.vacant);
}
};
// add tax lot layer button event listeners
var initButtons = function() {
$('.button').click(function() {
$('.button').removeClass('selected');
$(this).addClass('selected');
taxLotActions[$(this).attr('id')]();
});
}
// change dob permit layer sql based on check box boolean
var initCheckboxesTwo = function() {
// checkboxes for dob permit layer
var checkboxDOB = $('input.dob:checkbox'),
$a1 = $('#a1'),
$a2a3 = $('#a2a3'),
$nb = $('#nb');
// toggle A1 major alterations
$a1.change(function(){
if ($a1.is(':checked')){
el.dobPermitsA1.show();
// el.dobPermitsA1.setInteraction(true);
el.dobPermitsA1.setInteractivity('address');
} else {
el.dobPermitsA1.hide();
};
});
// toggle A2, A3 minor alterations
$a2a3.change(function(){
if ($a2a3.is(':checked')){
el.dobPermitsA2A3.show();
// el.dobPermitsA2A3.setInteraction(true);
//el.dobPermitsA2A3.setInteractivity('address, job, initialcos, jt_description, ownerphone, ownername, ownertype');
} else {
el.dobPermitsA2A3.hide();
};
});
// toggle NB new buildings
$nb.change(function(){
if ($nb.is(':checked')){
el.dobPermitsNB.show();
// el.dobPermitsNB.setInteraction(true);
// el.dobPermitsNB.setInteractivity('address, job, initialcos, jt_description, ownerphone, ownername, ownertype');
} else {
el.dobPermitsNB.hide();
};
});
}
// get it going!
var init = function() {
initMap();
initButtons();
initCheckboxesTwo();
}
// only return init() and the stuff in the el object
return {
init : init,
el : el
}
})(window, document, jQuery, _);
// call app.map.init() once the dom is loaded
window.addEventListener('DOMContentLoaded', function(){
app.map.init();
timerangeUI();
});
/**** CartoCSS for styling tax lot data ****/
var app = app || {};
app.mapStyles = (function(){
return {
// default style, all lots are the same color
regular : '#bushwick_pluto14v1 {' +
'polygon-fill: hsl(200,50%,50%);' +
'polygon-opacity: 0.75;' +
'line-color: #000;' +
'line-width: 0.2;' +
'line-opacity: 0.5;' +
'}',
// red highlight
red : '#bushwick_pluto14v1 {' +
'polygon-fill: hsl(0,100%,30%);' +
'polygon-opacity: 0.75;' +
'line-color: #000;' +
'line-width: 0.2;' +
'line-opacity: 0.5;' +
'}',
// category style based on zoning
zoning : "#bushwick_pluto14v1 {" +
"polygon-opacity: 0.75;" +
"line-color: #000;" +
"line-width: 0.2;" +
"line-opacity: 0.5;" +
"}" +
'#bushwick_pluto14v1[zoning_style="R"] { polygon-fill: #A6CEE3;}' +
'#bushwick_pluto14v1[zoning_style="RC"] {polygon-fill: #1F78B4;}' +
'#bushwick_pluto14v1[zoning_style="M"] {polygon-fill: #FFCC00;}' +
'#bushwick_pluto14v1[zoning_style="C"] {polygon-fill: #7B00B4;}' +
'#bushwick_pluto14v1[zoning_style="P"] {polygon-fill: #229A00;}' +
'#bushwick_pluto14v1[zoning_style=""] {polygon-fill: #6b6868;}',
// choropleth style based on Built FAR
builtFAR : "#bushwick_pluto14v1 {" +
"polygon-fill: #F1EEF6;" +
"polygon-opacity: 0.8;" +
"line-color: #000;" +
"line-width: 0.2;" +
"line-opacity: 0.5;" +
"}" +
'#bushwick_pluto14v1[builtfar <= 23.05] { polygon-fill: #91003F;}' +
'#bushwick_pluto14v1[builtfar <= 8.59] {polygon-fill: #CE1256;}' +
'#bushwick_pluto14v1[builtfar <= 3.95] {polygon-fill: #E7298A;}' +
'#bushwick_pluto14v1[builtfar <= 3.53] {polygon-fill: #DF65B0;}' +
'#bushwick_pluto14v1[builtfar <= 2.7] {polygon-fill: #C994C7;}' +
'#bushwick_pluto14v1[builtfar <= 1.57] {polygon-fill: #D4B9DA;}'+
'#bushwick_pluto14v1[builtfar <= 1.55]{polygon-fill: #F1EEF6;}',
// choropleth style based on Residential FAR
residFAR : "#bushwick_pluto14v1 {" +
"polygon-fill: #FFFFB2;" +
"polygon-opacity: 0.8;" +
"line-color: #000;" +
"line-width: 0.2;" +
"line-opacity: 0.5;" +
"}" +
'#bushwick_pluto14v1[ residfar <= 3.44] { polygon-fill: #BD0026;}' +
'#bushwick_pluto14v1[ residfar <= 2.43] {polygon-fill: #F03B20;}' +
'#bushwick_pluto14v1[ residfar <= 0.9] {polygon-fill: #FD8D3C;}' +
'#bushwick_pluto14v1[ residfar <= 0.9] {polygon-fill: #FECC5C;}' +
'#bushwick_pluto14v1[ residfar <= 0.6] {polygon-fill: #FFFFB2;}',
// choropleth style for available FAR
availFAR : "#bushwick_pluto14v1{" +
"polygon-fill: #FFFFB2;" +
"polygon-opacity: 0.8;" +
"line-color: #000;" +
"line-width: 0.2;" +
"line-opacity: 0.5;" +
"}" +
"#bushwick_pluto14v1 [ availablefar <= 4] {" +
"polygon-fill: #BD0026;" +
"}" +
"#bushwick_pluto14v1 [ availablefar <= 3.2] {" +
"polygon-fill: #F03B20;" +
"}" +
"#bushwick_pluto14v1 [ availablefar <= 2.4000000000000004] {" +
"polygon-fill: #FD8D3C;" +
"}" +
"#bushwick_pluto14v1 [ availablefar <= 1.6] {" +
"polygon-fill: #FECC5C;" +
"}" +
"#bushwick_pluto14v1 [ availablefar <= 0.8] {" +
"polygon-fill: #FFFFB2;" +
"}",
landuse : "#bushwick_pluto14v1 {" +
"polygon-opacity: 0.7;" +
"line-color: #000000;"+
"line-width: 0.2;"+
"line-opacity: 0.5;"+
"}"+
'#bushwick_pluto14v1[lu_descript="Multi-Family Walkup"] {'+
'polygon-fill: #A6CEE3;'+
'}'+
'#bushwick_pluto14v1[lu_descript="One and Two Family Buildings"] {'+
'polygon-fill: #1F78B4;'+
'}'+
'#bushwick_pluto14v1[lu_descript="Mixed Residential & Commerical"] {'+
'polygon-fill: #B2DF8A;'+
'}'+
'#bushwick_pluto14v1[lu_descript="Parking Facilities"] {'+
'polygon-fill: #33A02C;'+
'}'+
'#bushwick_pluto14v1[lu_descript="Vacant Land"] {'+
'polygon-fill: #FB9A99;'+
'}'+
'#bushwick_pluto14v1[lu_descript="Commerical & Office"] {'+
'polygon-fill: #E31A1C;'+
'}'+
'#bushwick_pluto14v1[lu_descript="Industrial & Manufacturing"] {'+
'polygon-fill: #FDBF6F;'+
'}'+
'#bushwick_pluto14v1[lu_descript="Public Facilities & Insitutions"] {'+
'polygon-fill: #FF7F00;'+
'}'+
'#bushwick_pluto14v1[lu_descript="N/A"] {'+
'polygon-fill: #CAB2D6;'+
'}'+
'#bushwick_pluto14v1[lu_descript="Open Space & Recreation"] {'+
'polygon-fill: #6A3D9A;'+
'}'+
'#bushwick_pluto14v1 {'+
'polygon-fill: #DDDDDD;'+
"}"
};
})();
/* new styles */
html, body {
height: 100%;
width: 100%;
margin: 0;
border: 0;
padding: 0;
font-family: Helvetica, Arial, sans-serif;
font-size: 13px;
}
* {
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box; /* Opera/IE 8+ */;
}
#map {
width: 100%;
height: 100%;
}
#tool-tip {
position: absolute;
width: auto;
height: auto;
background-color: white;
opacity: .9;
z-index: 150;
border-radius: 15px;
text-align: center;
color: #3E7BB6;
vertical-align: bottom;
font-family: Helvetica, sans-serif;
font-weight: 400;
font-size: 12px;
padding: 4px;
}
#tool-tip p {
margin-top: 5px;
}
#menu{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 40px;
background-color: hsla(0, 100%, 30%, 0.75);
z-index: 100;
}
#intro{
position: absolute;
top: 40px;
left: 40px;
width: 360px;
padding: 12px;
background-color: hsla(0, 100%, 30%, 0.75);
color: white;
z-index: 90;
}
#intro h1{
margin: 0 0 12px 0;
}
input:focus,
select:focus,
textarea:focus,
button:focus {
outline: none;
}
input{
font-family: Helvetica, Arial, sans-serif;
font-size: 13px;
}
.ui{
background-color: hsla(0, 0%, 100%, 0.92);
border: 2px solid hsl(0, 100%, 35%);
border-radius: 14px;
}
#history{
position: absolute;
left: 40px;
bottom: 40px;
width: 880px;
height: 56px;
padding: 12px;
z-index: 85;
}
.year{
position: absolute;
border: 0 none;
text-align: center;
color: hsl(0, 0%, 50%);
}
#slider-container{
position: relative;
width: 85%;
/*height: 40px;*/
margin: 0 24px 0 24px;
display: inline-block;
}
#search-button{
position: absolute;
top: 65px;
right: 46px;
width: 24px;
height: 24px;
border: 0;
background: url('../images/search_button.svg') no-repeat;
z-index: 80;
}
#search-box{
position: absolute;
top: 60px;
right: 40px;
width: 280px;
height: 28px;
padding: 0 36px 0 12px;
z-index: 70;
}
#ui-container {
position: absolute;
top: 108px;
right: 40px;
width: 200px;
padding: 12px;
z-index: 60;
}
.ui h4 {
padding: 0;
margin: 0;
color: hsl(0, 100%, 35%);
font-size: 16px;
display: inline-block;
}
.ui a{
width: 100%;
margin: 4px 0 4px 0;
padding: 2px 8px 2px 8px;
display: block;
color: black;
background-color: hsl(0, 0%, 98%);
box-shadow: inset 0px -15px 10px -12px hsla(0, 0%, 0%, 0.05);
border: 1px solid hsl(0, 0%, 85%);
border-radius: 4px;
text-decoration: none;
}
.ui a.selected,
.ui a:hover {
color: white;
background-color: hsl(0, 100%, 35%);
border: 1px solid hsl(0, 100%, 25%);
}
.ui hr{
background-color: hsl(0, 100%, 35%);
height: 1px;
border-width: 0;
margin: 8px 0 8px 0;
}
label {
/*display: block;*/
vertical-align: middle;
margin: 2px 4px 2px 0;
}
.regular-checkbox {
display: none;
}
.regular-checkbox + label {
background-color: #fafafa;
border: 1px solid #cacece;
box-shadow: inset 0px -15px 10px -12px rgba(0,0,0,0.05);
padding: 9px;
border-radius: 3px;
display: inline-block;
position: relative;
}
.regular-checkbox + label:active, .regular-checkbox:checked + label:active {
box-shadow: inset 0px -15px 10px -12px rgba(0,0,0,0.05);
}
.regular-checkbox:checked + label {
box-shadow: inset 0px -15px 10px -12px rgba(0,0,0,0.05);
color: #99a1a7;
}
.regular-checkbox:checked + label:after {
content: '\2714';
font-size: 12px;
position: absolute;
top: 0px;
left: 3px;
color: hsl(0, 100%, 35%); ;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment