var map, featureList, boroughSearch = [], theaterSearch = [], museumSearch = [];

$(window).resize(function() {

sizeLayerControl();

});

$(document).on(“click”, “.feature-row”, function(e) {

$(document).off("mouseout", ".feature-row", clearHighlight);
sidebarClick(parseInt($(this).attr("id"), 10));

});

if ( !(“ontouchstart” in window) ) {

$(document).on("mouseover", ".feature-row", function(e) {
  highlight.clearLayers().addLayer(L.circleMarker([$(this).attr("lat"), $(this).attr("lng")], highlightStyle));
});

}

$(document).on(“mouseout”, “.feature-row”, clearHighlight);

$(“#about-btn”).click(function() {

$("#aboutModal").modal("show");
$(".navbar-collapse.in").collapse("hide");
return false;

});

$(“#full-extent-btn”).click(function() {

map.fitBounds(boroughs.getBounds());
$(".navbar-collapse.in").collapse("hide");
return false;

});

$(“#legend-btn”).click(function() {

$("#legendModal").modal("show");
$(".navbar-collapse.in").collapse("hide");
return false;

});

$(“#login-btn”).click(function() {

$("#loginModal").modal("show");
$(".navbar-collapse.in").collapse("hide");
return false;

});

$(“#list-btn”).click(function() {

animateSidebar();
return false;

});

$(“#nav-btn”).click(function() {

$(".navbar-collapse").collapse("toggle");
return false;

});

$(“#sidebar-toggle-btn”).click(function() {

animateSidebar();
return false;

});

$(“#sidebar-hide-btn”).click(function() {

animateSidebar();
return false;

});

function animateSidebar() {

$("#sidebar").animate({
  width: "toggle"
}, 350, function() {
  map.invalidateSize();
});

}

function sizeLayerControl() {

$(".leaflet-control-layers").css("max-height", $("#map").height() - 50);

}

function clearHighlight() {

highlight.clearLayers();

}

function sidebarClick(id) {

var layer = markerClusters.getLayer(id);
map.setView([layer.getLatLng().lat, layer.getLatLng().lng], 17);
layer.fire("click");
/* Hide sidebar and go to the map on small screens */
if (document.body.clientWidth <= 767) {
  $("#sidebar").hide();
  map.invalidateSize();
}

}

function syncSidebar() {

/* Empty sidebar features */
$("#feature-list tbody").empty();
/* Loop through theaters layer and add only features which are in the map bounds */
theaters.eachLayer(function (layer) {
  if (map.hasLayer(theaterLayer)) {
    if (map.getBounds().contains(layer.getLatLng())) {
      $("#feature-list tbody").append('<tr class="feature-row" id="' + L.stamp(layer) + '" lat="' + layer.getLatLng().lat + '" lng="' + layer.getLatLng().lng + '"><td style="vertical-align: middle;"><img width="16" height="18" src="assets/img/theater.png"></td><td class="feature-name">' + layer.feature.properties.NAME + '</td><td style="vertical-align: middle;"><i class="fa fa-chevron-right pull-right"></i></td></tr>');
    }
  }
});
/* Loop through museums layer and add only features which are in the map bounds */
museums.eachLayer(function (layer) {
  if (map.hasLayer(museumLayer)) {
    if (map.getBounds().contains(layer.getLatLng())) {
      $("#feature-list tbody").append('<tr class="feature-row" id="' + L.stamp(layer) + '" lat="' + layer.getLatLng().lat + '" lng="' + layer.getLatLng().lng + '"><td style="vertical-align: middle;"><img width="16" height="18" src="assets/img/museum.png"></td><td class="feature-name">' + layer.feature.properties.NAME + '</td><td style="vertical-align: middle;"><i class="fa fa-chevron-right pull-right"></i></td></tr>');
    }
  }
});
/* Update list.js featureList */
featureList = new List("features", {
  valueNames: ["feature-name"]
});
featureList.sort("feature-name", {
  order: "asc"
});

}

/* Basemap Layers */ var cartoLight = L.tileLayer(“”, {

maxZoom: 19,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="https://cartodb.com/attributions">CartoDB</a>'

}); var usgsImagery = L.layerGroup([L.tileLayer(“basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}”, {

maxZoom: 15,

}), L.tileLayer.wms(“raster.nationalmap.gov/arcgis/services/Orthoimagery/USGS_EROS_Ortho_SCALE/ImageServer/WMSServer?”, {

minZoom: 16,
maxZoom: 19,
layers: "0",
format: 'image/jpeg',
transparent: true,
attribution: "Aerial Imagery courtesy USGS"

})]);

/* Overlay Layers */ var highlight = L.geoJson(null); var highlightStyle = {

stroke: false,
fillColor: "#00FFFF",
fillOpacity: 0.7,
radius: 10

};

var boroughs = L.geoJson(null, {

style: function (feature) {
  return {
    color: "black",
    fill: false,
    opacity: 1,
    clickable: false
  };
},
onEachFeature: function (feature, layer) {
  boroughSearch.push({
    name: layer.feature.properties.BoroName,
    source: "Boroughs",
    id: L.stamp(layer),
    bounds: layer.getBounds()
  });
}

}); $.getJSON(“assets/data/boroughs.geojson”, function (data) {

boroughs.addData(data);

});

//Create a color dictionary based off of subway route_id var subwayColors = {“1”:“#ff3135”, “2”:“#ff3135”, “3”:“ff3135”, “4”:“#009b2e”,

"5":"#009b2e", "6":"#009b2e", "7":"#ce06cb", "A":"#fd9a00", "C":"#fd9a00",
"E":"#fd9a00", "SI":"#fd9a00","H":"#fd9a00", "Air":"#ffff00", "B":"#ffff00",
"D":"#ffff00", "F":"#ffff00", "M":"#ffff00", "G":"#9ace00", "FS":"#6e6e6e",
"GS":"#6e6e6e", "J":"#976900", "Z":"#976900", "L":"#969696", "N":"#ffff00",
"Q":"#ffff00", "R":"#ffff00" };

var subwayLines = L.geoJson(null, {

style: function (feature) {
    return {
      color: subwayColors[feature.properties.route_id],
      weight: 3,
      opacity: 1
    };
},
onEachFeature: function (feature, layer) {
  if (feature.properties) {
    var content = "<table class='table table-striped table-bordered table-condensed'>" + "<tr><th>Division</th><td>" + feature.properties.Division + "</td></tr>" + "<tr><th>Line</th><td>" + feature.properties.Line + "</td></tr>" + "<table>";
    layer.on({
      click: function (e) {
        $("#feature-title").html(feature.properties.Line);
        $("#feature-info").html(content);
        $("#featureModal").modal("show");
      }
    });
  }
  layer.on({
    mouseover: function (e) {
      var layer = e.target;
      layer.setStyle({
        weight: 3,
        color: "#00FFFF",
        opacity: 1
      });
      if (!L.Browser.ie && !L.Browser.opera) {
        layer.bringToFront();
      }
    },
    mouseout: function (e) {
      subwayLines.resetStyle(e.target);
    }
  });
}

}); $.getJSON(“assets/data/subways.geojson”, function (data) {

subwayLines.addData(data);

});

/* Single marker cluster layer to hold all clusters */ var markerClusters = new L.MarkerClusterGroup({

spiderfyOnMaxZoom: true,
showCoverageOnHover: false,
zoomToBoundsOnClick: true,
disableClusteringAtZoom: 16

});

/* Empty layer placeholder to add to layer control for listening when to add/remove theaters to markerClusters layer */ var theaterLayer = L.geoJson(null); var theaters = L.geoJson(null, {

pointToLayer: function (feature, latlng) {
  return L.marker(latlng, {
    icon: L.icon({
      iconUrl: "assets/img/theater.png",
      iconSize: [24, 28],
      iconAnchor: [12, 28],
      popupAnchor: [0, -25]
    }),
    title: feature.properties.NAME,
    riseOnHover: true
  });
},
onEachFeature: function (feature, layer) {
  if (feature.properties) {
    var content = "<table class='table table-striped table-bordered table-condensed'>" + "<tr><th>Name</th><td>" + feature.properties.NAME + "</td></tr>" + "<tr><th>Phone</th><td>" + feature.properties.TEL + "</td></tr>" + "<tr><th>Address</th><td>" + feature.properties.ADDRESS1 + "</td></tr>" + "<tr><th>Website</th><td><a class='url-break' href='" + feature.properties.URL + "' target='_blank'>" + feature.properties.URL + "</a></td></tr>" + "<table>";
    layer.on({
      click: function (e) {
        $("#feature-title").html(feature.properties.NAME);
        $("#feature-info").html(content);
        $("#featureModal").modal("show");
        highlight.clearLayers().addLayer(L.circleMarker([feature.geometry.coordinates[1], feature.geometry.coordinates[0]], highlightStyle));
      }
    });
    $("#feature-list tbody").append('<tr class="feature-row" id="' + L.stamp(layer) + '" lat="' + layer.getLatLng().lat + '" lng="' + layer.getLatLng().lng + '"><td style="vertical-align: middle;"><img width="16" height="18" src="assets/img/theater.png"></td><td class="feature-name">' + layer.feature.properties.NAME + '</td><td style="vertical-align: middle;"><i class="fa fa-chevron-right pull-right"></i></td></tr>');
    theaterSearch.push({
      name: layer.feature.properties.NAME,
      address: layer.feature.properties.ADDRESS1,
      source: "Theaters",
      id: L.stamp(layer),
      lat: layer.feature.geometry.coordinates[1],
      lng: layer.feature.geometry.coordinates[0]
    });
  }
}

}); $.getJSON(“assets/data/DOITT_THEATER_01_13SEPT2010.geojson”, function (data) {

theaters.addData(data);
map.addLayer(theaterLayer);

});

/* Empty layer placeholder to add to layer control for listening when to add/remove museums to markerClusters layer */ var museumLayer = L.geoJson(null); var museums = L.geoJson(null, {

pointToLayer: function (feature, latlng) {
  return L.marker(latlng, {
    icon: L.icon({
      iconUrl: "assets/img/museum.png",
      iconSize: [24, 28],
      iconAnchor: [12, 28],
      popupAnchor: [0, -25]
    }),
    title: feature.properties.NAME,
    riseOnHover: true
  });
},
onEachFeature: function (feature, layer) {
  if (feature.properties) {
    var content = "<table class='table table-striped table-bordered table-condensed'>" + "<tr><th>Name</th><td>" + feature.properties.NAME + "</td></tr>" + "<tr><th>Phone</th><td>" + feature.properties.TEL + "</td></tr>" + "<tr><th>Address</th><td>" + feature.properties.ADRESS1 + "</td></tr>" + "<tr><th>Website</th><td><a class='url-break' href='" + feature.properties.URL + "' target='_blank'>" + feature.properties.URL + "</a></td></tr>" + "<table>";
    layer.on({
      click: function (e) {
        $("#feature-title").html(feature.properties.NAME);
        $("#feature-info").html(content);
        $("#featureModal").modal("show");
        highlight.clearLayers().addLayer(L.circleMarker([feature.geometry.coordinates[1], feature.geometry.coordinates[0]], highlightStyle));
      }
    });
    $("#feature-list tbody").append('<tr class="feature-row" id="' + L.stamp(layer) + '" lat="' + layer.getLatLng().lat + '" lng="' + layer.getLatLng().lng + '"><td style="vertical-align: middle;"><img width="16" height="18" src="assets/img/museum.png"></td><td class="feature-name">' + layer.feature.properties.NAME + '</td><td style="vertical-align: middle;"><i class="fa fa-chevron-right pull-right"></i></td></tr>');
    museumSearch.push({
      name: layer.feature.properties.NAME,
      address: layer.feature.properties.ADRESS1,
      source: "Museums",
      id: L.stamp(layer),
      lat: layer.feature.geometry.coordinates[1],
      lng: layer.feature.geometry.coordinates[0]
    });
  }
}

}); $.getJSON(“assets/data/DOITT_MUSEUM_01_13SEPT2010.geojson”, function (data) {

museums.addData(data);

});

map = L.map(“map”, {

zoom: 10,
center: [40.702222, -73.979378],
layers: [cartoLight, boroughs, markerClusters, highlight],
zoomControl: false,
attributionControl: false

});

/* Layer control listeners that allow for a single markerClusters layer */ map.on(“overlayadd”, function(e) {

if (e.layer === theaterLayer) {
  markerClusters.addLayer(theaters);
  syncSidebar();
}
if (e.layer === museumLayer) {
  markerClusters.addLayer(museums);
  syncSidebar();
}

});

map.on(“overlayremove”, function(e) {

if (e.layer === theaterLayer) {
  markerClusters.removeLayer(theaters);
  syncSidebar();
}
if (e.layer === museumLayer) {
  markerClusters.removeLayer(museums);
  syncSidebar();
}

});

/* Filter sidebar feature list to only show features in current map bounds */ map.on(“moveend”, function (e) {

syncSidebar();

});

/* Clear feature highlight when map is clicked */ map.on(“click”, function(e) {

highlight.clearLayers();

});

/* Attribution control */ function updateAttribution(e) {

$.each(map._layers, function(index, layer) {
  if (layer.getAttribution) {
    $("#attribution").html((layer.getAttribution()));
  }
});

} map.on(“layeradd”, updateAttribution); map.on(“layerremove”, updateAttribution);

var attributionControl = L.control({

position: "bottomright"

}); attributionControl.onAdd = function (map) {

var div = L.DomUtil.create("div", "leaflet-control-attribution");
div.innerHTML = "<span class='hidden-xs'>Developed by <a href='http://bryanmcbride.com'>bryanmcbride.com</a> | </span><a href='#' onclick='$(\"#attributionModal\").modal(\"show\"); return false;'>Attribution</a>";
return div;

}; map.addControl(attributionControl);

var zoomControl = L.control.zoom({

position: "bottomright"

}).addTo(map);

/* GPS enabled geolocation control set to follow the user's location */ var locateControl = L.control.locate({

position: "bottomright",
drawCircle: true,
follow: true,
setView: true,
keepCurrentZoomLevel: true,
markerStyle: {
  weight: 1,
  opacity: 0.8,
  fillOpacity: 0.8
},
circleStyle: {
  weight: 1,
  clickable: false
},
icon: "fa fa-location-arrow",
metric: false,
strings: {
  title: "My location",
  popup: "You are within {distance} {unit} from this point",
  outsideMapBoundsMsg: "You seem located outside the boundaries of the map"
},
locateOptions: {
  maxZoom: 18,
  watch: true,
  enableHighAccuracy: true,
  maximumAge: 10000,
  timeout: 10000
}

}).addTo(map);

/* Larger screens get expanded layer control and visible sidebar */ if (document.body.clientWidth <= 767) {

var isCollapsed = true;

} else {

var isCollapsed = false;

}

var baseLayers = {

"Street Map": cartoLight,
"Aerial Imagery": usgsImagery

};

var groupedOverlays = {

"Points of Interest": {
  "<img src='assets/img/theater.png' width='24' height='28'>&nbsp;Theaters": theaterLayer,
  "<img src='assets/img/museum.png' width='24' height='28'>&nbsp;Museums": museumLayer
},
"Reference": {
  "Boroughs": boroughs,
  "Subway Lines": subwayLines
}

};

var layerControl = L.control.groupedLayers(baseLayers, groupedOverlays, {

collapsed: isCollapsed

}).addTo(map);

/* Highlight search box text on click */ $(“#searchbox”).click(function () {

$(this).select();

});

/* Prevent hitting enter from refreshing the page */ $(“#searchbox”).keypress(function (e) {

if (e.which == 13) {
  e.preventDefault();
}

});

$(“#featureModal”).on(“hidden.bs.modal”, function (e) {

$(document).on("mouseout", ".feature-row", clearHighlight);

});

/* Typeahead search functionality */ $(document).one(“ajaxStop”, function () {

$("#loading").hide();
sizeLayerControl();
/* Fit map to boroughs bounds */
map.fitBounds(boroughs.getBounds());
featureList = new List("features", {valueNames: ["feature-name"]});
featureList.sort("feature-name", {order:"asc"});
var boroughsBH = new Bloodhound({
  name: "Boroughs",
  datumTokenizer: function (d) {
    return Bloodhound.tokenizers.whitespace(d.name);
  },
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  local: boroughSearch,
  limit: 10
});
var theatersBH = new Bloodhound({
  name: "Theaters",
  datumTokenizer: function (d) {
    return Bloodhound.tokenizers.whitespace(d.name);
  },
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  local: theaterSearch,
  limit: 10
});
var museumsBH = new Bloodhound({
  name: "Museums",
  datumTokenizer: function (d) {
    return Bloodhound.tokenizers.whitespace(d.name);
  },
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  local: museumSearch,
  limit: 10
});
var geonamesBH = new Bloodhound({
  name: "GeoNames",
  datumTokenizer: function (d) {
    return Bloodhound.tokenizers.whitespace(d.name);
  },
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  remote: {
    url: "http://api.geonames.org/searchJSON?username=bootleaf&featureClass=P&maxRows=5&countryCode=US&name_startsWith=%QUERY",
    filter: function (data) {
      return $.map(data.geonames, function (result) {
        return {
          name: result.name + ", " + result.adminCode1,
          lat: result.lat,
          lng: result.lng,
          source: "GeoNames"
        };
      });
    },
    ajax: {
      beforeSend: function (jqXhr, settings) {
        settings.url += "&east=" + map.getBounds().getEast() + "&west=" + map.getBounds().getWest() + "&north=" + map.getBounds().getNorth() + "&south=" + map.getBounds().getSouth();
        $("#searchicon").removeClass("fa-search").addClass("fa-refresh fa-spin");
      },
      complete: function (jqXHR, status) {
        $('#searchicon').removeClass("fa-refresh fa-spin").addClass("fa-search");
      }
    }
  },
  limit: 10
});
boroughsBH.initialize();
theatersBH.initialize();
museumsBH.initialize();
geonamesBH.initialize();
/* instantiate the typeahead UI */
$("#searchbox").typeahead({
  minLength: 3,
  highlight: true,
  hint: false
}, {
  name: "Boroughs",
  displayKey: "name",
  source: boroughsBH.ttAdapter(),
  templates: {
    header: "<h4 class='typeahead-header'>Boroughs</h4>"
  }
}, {
  name: "Theaters",
  displayKey: "name",
  source: theatersBH.ttAdapter(),
  templates: {
    header: "<h4 class='typeahead-header'><img src='assets/img/theater.png' width='24' height='28'>&nbsp;Theaters</h4>",
    suggestion: Handlebars.compile(["{{name}}<br>&nbsp;<small>{{address}}</small>"].join(""))
  }
}, {
  name: "Museums",
  displayKey: "name",
  source: museumsBH.ttAdapter(),
  templates: {
    header: "<h4 class='typeahead-header'><img src='assets/img/museum.png' width='24' height='28'>&nbsp;Museums</h4>",
    suggestion: Handlebars.compile(["{{name}}<br>&nbsp;<small>{{address}}</small>"].join(""))
  }
}, {
  name: "GeoNames",
  displayKey: "name",
  source: geonamesBH.ttAdapter(),
  templates: {
    header: "<h4 class='typeahead-header'><img src='assets/img/globe.png' width='25' height='25'>&nbsp;GeoNames</h4>"
  }
}).on("typeahead:selected", function (obj, datum) {
  if (datum.source === "Boroughs") {
    map.fitBounds(datum.bounds);
  }
  if (datum.source === "Theaters") {
    if (!map.hasLayer(theaterLayer)) {
      map.addLayer(theaterLayer);
    }
    map.setView([datum.lat, datum.lng], 17);
    if (map._layers[datum.id]) {
      map._layers[datum.id].fire("click");
    }
  }
  if (datum.source === "Museums") {
    if (!map.hasLayer(museumLayer)) {
      map.addLayer(museumLayer);
    }
    map.setView([datum.lat, datum.lng], 17);
    if (map._layers[datum.id]) {
      map._layers[datum.id].fire("click");
    }
  }
  if (datum.source === "GeoNames") {
    map.setView([datum.lat, datum.lng], 14);
  }
  if ($(".navbar-collapse").height() > 50) {
    $(".navbar-collapse").collapse("hide");
  }
}).on("typeahead:opened", function () {
  $(".navbar-collapse.in").css("max-height", $(document).height() - $(".navbar-header").height());
  $(".navbar-collapse.in").css("height", $(document).height() - $(".navbar-header").height());
}).on("typeahead:closed", function () {
  $(".navbar-collapse.in").css("max-height", "");
  $(".navbar-collapse.in").css("height", "");
});
$(".twitter-typeahead").css("position", "static");
$(".twitter-typeahead").css("display", "block");

});

// Leaflet patch to make layer control scrollable on touch browsers var container = $(“.leaflet-control-layers”); if (!L.Browser.touch) {

L.DomEvent
.disableClickPropagation(container)
.disableScrollPropagation(container);

} else {

L.DomEvent.disableClickPropagation(container);

}