<html> <head> <title>NYC Bookstores</title> <meta charset='utf-8'> <script type="text/javascript" src='js/jquery.js'></script> <script type="text/javascript" src='js/mustache.js'></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <script src='https://api.mapbox.com/mapbox-gl-js/v0.34.0/mapbox-gl.js'></script> <link href='https://api.mapbox.com/mapbox-gl-js/v0.34.0/mapbox-gl.css' rel='stylesheet' /> <link href="https://fonts.googleapis.com/css?family=Acme|Lato" rel="stylesheet"> <link media="screen" rel="stylesheet" type="text/css" href="css/site.css"> <meta name="twitter:card" content="summary" /> <meta name="twitter:site" content="www.nycbookstores.org" /> <meta name="twitter:title" content="NYC Bookstores" /> <meta name="twitter:description" content="A Guide To The Many Independent Bookstores Of New York City" /> <meta name="twitter:image" content="http://www.nycbookstores.org/img/social.jpg" /> <meta property="og:url" content="http://www.nycbookstores.org/" /> <meta property="og:title" content="NYC Bookstores" /> <meta property="og:description" content="A Guide To The Many Independent Bookstores Of New York City" /> <meta property="og:image" content="http://www.nycbookstores.org/img/social.jpg" /> </head> <body> <div id="wrapper"> <h1>NYC Bookstores</h1> <div> <ul class="nav"> <li><strong>The Many Independent Bookstores of New York City</strong></li> <li><a id='viewInfo'>info</a></li> <li><a href="https://github.com/nyc-bookstores/nyc-bookstores.github.io" target="_blank">github</a></li> <li><a href="http://www.twitter.com/alazyreader" target="_blank">@alazyreader</a></li> </ul> </div> <div class="container"> <div id='map'></div> <div id='info'> <p>Although the bookselling community of New York City is much depleted from its heyday, there still are independent bookstores out there. Unfortunately, there has also been a lack of resources available to discover and visit the stores that do exist. This site, while not on the level of the old guides, can help with that.</p> <p>While the data here are kept up-to-date to the best of my ability, I make no promises about the accuracy of locations or other details presented. If you spot an error, or I've missed a shop, please let me know by <a href="mailto:delta.mu.alpha@gmail.com">email</a> or <a href="https://www.twitter.com/alazyreader">twitter</a>. Based on the "<a href="https://github.com/jlord/hack-spots">Hack Spots</a>" website by <a href="http://www.twitter.com/jllord" target="_blank">@jllord</a>. </div> <div id='selected'></div> </div> <div class="clearfix"></div> <div class="container"> <div id="Stores"></div> </div> </div><!-- end wrapper --> <script id="Table" type="text/html"> <table> <tr><th class="tHeader">Name</th><th class="tHeader">Address</th></tr> {{#rows}} <tr id="{{rowNumber}}" class="spotRow"> <td>{{name}}</td> <td>{{address}}, {{city}}</td> </tr> {{/rows}} </table> </script> <script id="selectedStore" type="text/html"> {{#store}} <h2>{{name}}</h2> <p class="address">{{address}}<p> <p class="address">{{city}},NY {{#postcode}} {{postcode}} {{/postcode}}</p> <p> <a href="https://maps.google.com/maps?q={{name}} {{address}},{{city}},NY" target="_blank">View in Google Maps</a> </p> <ul> <li> <span class="store-details">Events:</span> {{events}} <span class="store-details">Café:</span> {{cafe}} </li> {{#website}} <li><span class="store-details">Website:</span> <a href='{{website}}' target="_blank">{{website}}</a></li> {{/website}} </ul> {{#description}} <p class="description">{{description}}</p> {{/description}} {{/store}} </script> <script> mapboxgl.accessToken = 'pk.eyJ1IjoiYWxhenlyZWFkZXIiLCJhIjoiY2lucDZhb2JxMHp6MHRxa2pvaTFoOWpuZyJ9.DILGYYxxt7A-A_lHHwp6tQ'; var map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/basic-v9', center: [-73.8966279, 40.7420127], // arbitrary center point zoom: 10 }); var popup = new mapboxgl.Popup({ closeOnClick: false, closeButton: false }); document.addEventListener('DOMContentLoaded', function() { $.getJSON('./stores.json', function(data) { data.sort( function(a, b) { var aname = a.name.toLowerCase(); var bname = b.name.toLowerCase(); return aname === bname ? 0 : +(aname > bname) || -1; } ) $.each(data, function(key, value) { value.rowNumber = key; }); loadMap(data); }); }); function boundingBox(point) { // add some buffer to a point to give the user some leeway return [[point.x - 5, point.y - 5], [point.x + 5, point.y + 5]] } function updateSelectedStore(store) { map.flyTo({center: [store.long, store.lat]}); popup.setLngLat([store.long, store.lat]) .setHTML(store.name) .addTo(map); $('#info').hide(); var template = $('#selectedStore').html(); var rendered = Mustache.render(template, {store: store}); $('#selected').html(rendered); $('#selected').show(); } function showInfo() { $('#selected').hide(); $('#info').show(); } function loadMap(data) { var points = []; $.each(data, function(key, value) { points.push({ "type": "Feature", "geometry": { "type": "Point", "coordinates": [value.long, value.lat] }, "properties": value }); }); map.on('load', function () { map.addLayer({ "id": "stores", "type": "circle", "source": { "type": "geojson", "data": { "type": "FeatureCollection", "features": points } }, "paint": { "circle-radius": 5, "circle-color": "#B9FCFC", "circle-stroke-width": 2, "circle-stroke-color": "#000000" } }) map.addControl(new mapboxgl.NavigationControl(), 'top-left'); }); map.on('click', function (e) { if (!map.getLayer('stores')) { return; } popup.remove(); // Use queryRenderedFeatures to get features at a click event's point var features = map.queryRenderedFeatures(boundingBox(e.point), { layers: ['stores'] }); // fly to the location of the click event if (features.length) { var store = features[0]; // Get coordinates from the symbol and center the map on those coordinates updateSelectedStore(store.properties); } }); // indicate that the symbols are clickable by changing the cursor style to 'pointer'. map.on('mousemove', function (e) { if (!map.getLayer('stores')) { return; } var features = map.queryRenderedFeatures(boundingBox(e.point), { layers: ['stores'] }); map.getCanvas().style.cursor = features.length ? 'pointer' : ''; }); var template = $('#Table').html(); var rendered = Mustache.render(template, {rows: data}); $('#Stores').html(rendered); $("#Stores tbody tr").on("click", function() { updateSelectedStore(data[$(this)[0].id]); }); $('#viewInfo').on("click", showInfo); }; </script> </body> </html>