This commit is contained in:
David 2017-03-26 18:34:41 -04:00
parent 4ad3ef9f72
commit 2e36a486c1
14 changed files with 294 additions and 16765 deletions

View File

@ -25,7 +25,6 @@
"browser": true
},
"globals": {
"Sheetsee": true,
"$": true
}
}

5
.gitignore vendored
View File

@ -1,6 +1 @@
node_modules
server.js
test.js
package.json
.DS_Store
_site

View File

@ -1,10 +1,10 @@
/* Page Specific CSS */
body {font-family: Lato; background: #fff; color: #333; font-size: 16px; border: 52px #F8F8F8 solid; margin: 0px; padding: 20px 20px 200px 20px;}
h1 {font-size: 80px; font-family: Amatic SC; font-weight: normal; margin: 0px;}
h2 {font-size: 50px; font-family: Amatic SC; font-weight: normal; margin: 11px 0px;}
h3 {font-family: Amatic SC; font-size: 30px; margin: 10px 0px;}
h4 {font-family: Lato; font-size: 24px;}
body {font-family: 'Lato', sans-serif; background: #fff; color: #333; font-size: 16px; border: 52px #F8F8F8 solid; margin: 0px; padding: 20px 20px 20px 20px;}
h1 {font-size: 80px; font-family: 'Acme', sans-serif; font-weight: normal; margin: 0px;}
h2 {font-size: 40px; font-family: 'Acme', sans-serif; font-weight: normal; margin: 0px 0px;}
h3 {font-family: 'Acme', sans-serif; font-size: 30px; margin: 10px 0px;}
h4 {font-family: 'Lato', sans-serif; font-size: 24px;}
img {width: 100%;}
p a, a {color: #333; text-decoration: none; padding-bottom: 0px; border-bottom: 1px #FD9393 solid;}
@ -14,14 +14,14 @@ p {margin: 0px; padding: 0px; font-size: 12px;}
li {line-height: 19px; font-size: 12px;}
ol {line-height: 24px;}
a.button {border: none;}
.clearfix {clear: both;}
pre {word-wrap: break-word; padding: 14px; background: #F0F0F0; }
code {font-family: "Consolas", "Ubuntu Mono", monospace; line-height: 22px; font-size: 13px; color: #636363; font-weight: normal;}
.red-text {color: #FD9393;}
#map {height: 400px; max-width: 530px; min-width: 300px; background: #DADADA;}
#map {height: 500px; width: 450px; min-width: 300px; background: #FFFFFF; float: left;}
#map a {border: none;}
.mapboxgl-popup-content {font-family: 'Lato', sans-serif; font-size: 14px; padding: 10px;}
.container {margin: 24px 0px;}
#tableFilter {margin: 12px 0px; border: none; border-bottom: 1px solid #333; background-color: transparent; padding: 0px; font-family: Lato; color: #333; font-size: 13px; height: 22px;}
@ -34,36 +34,23 @@ ul.nav li {display: inline; font-size: 10px; letter-spacing: .1em; text-transfor
ul.nav li a {border: none;}
ul.nav li a:hover {border-bottom: 1px #FD9393 solid;}
#wrapper {margin: 0px auto; max-width: 900px; padding-top: 40px; /*margin-left: 250px;*/}
#wrapper {margin: 0px auto; padding: 40px; max-width: 900px}
.button {padding: 5px 5px; background-color: #BEBEBE; font-size: 10px; color: #fff;}
.button:hover {background: #B9FCFC; color: #47CCFC;}
.fauxButton {padding: 5px 5px; background-color: #FF4646; font-size: 11px; color: #fff; display: inline;}
.fauxButton .selected {background-color: #FF4646;}
.colorText {color: #FF4646; text-transform: uppercase; font-weight: 700;}
.leaflet-popup-content h2 {font-family: Lato; font-size: 14px; text-transform: uppercase;}
#rightSide {max-width: 350px; width: 100%; float: right; padding-top: 5px;}
#selectedSpot {display: none;}
#latestSpot ul, #selectedSpot ul {list-style: none; margin-top: 12px 0px; padding: 0px;}
#selected {max-width: 400px; width: 100%; float: left; padding: 5px 10px;}
#selected .description {font-size: 14px; padding: 4px; line-height: 19px; font-weight: 300; max-width: 530px; min-width: 300px; }
#info {max-width: 400px; width: 100%; float: left; padding: 5px 10px;}
.category {text-transform: uppercase; font-size: 9px; letter-spacing: .2em; padding-right: 6px;}
#viewInfo {cursor: pointer;}
#info p {font-size: 14px; padding: 4px; line-height: 19px; font-weight: 300; max-width: 530px; min-width: 300px; }
#hackSpotsTable {cursor: pointer; background: #fff; overflow-x: auto; padding-bottom: 20px;}
#hackSpotsTable table {min-width: 900px;}
#hackSpotsTable .tHeader:hover {color: #FF4646;}
.tHeader::after {content: " \2193 \2191 "; font-size: 10px; padding-left: 3px;}
.spotRow:hover {color: #FF4646;}
.spotRow {border-left: 3px solid #ff00ff;}
.hideRow {display: none;}
.selectedRow {color: #FF4C0D;}
@media only screen and (-webkit-min-device-pixel-ratio: 2) and (min-width: 320px) and (max-width: 1024px) {
body {border: 20px #F8F8F8 solid; margin: 0px; padding: 20px 20px 80px 20px;}
#tableFilter, .clear, .resetMap {display: none;}
#wrapper {max-width: 460px; padding-top: 20px;}
#hackSpotsTable, #map {min-width: 224px;}
#Stores, #map {min-width: 224px;}
}

View File

@ -1,53 +0,0 @@
/* General */
/* body {margin: 0px auto;}
a {color: #333;}
small {padding: 10px 0px;}
#wrapper {margin: 0px auto; max-width: 600px;}
.button {padding: 5px 4px; background-color: #fff; font-size: 10px;}*/
.button:hover {cursor: hand;}
input:focus {outline: none;}
/* Table */
table {text-align: left; width: 100%}
th {padding: 10px 0px;}
td, text {padding: 3px 0 3px 0; font-size: 14px;}
#tableFilter {margin: 12px 0px; border: none; border-bottom: 1px solid #333; background-color: transparent; padding: 0px; font-family: Merriweather; color: #fff; font-size: 13px; height: 22px;}
.noMatches {margin-left: 20px; font-size: 11px; font-style: italic; visibility: hidden;}
/* Containers */
.container {margin: 14px 0px;}
#map {height: 400px; max-width: 800px; background: #DADADA;}
#holder {height: 400px; max-width: 600px; background: #FFE4E4;}
#bar2 {height: 320px; max-width: 600px; background: #F8CDCD;}
/* Bar Chart */
.labels text {text-align: right;}
.bar .labels text {fill: #333;}
.bar rect {fill: #e6e6e6;}
.axis {shape-rendering: crispEdges;}
.x.axis line {stroke: #FFE4E4; /*stroke-opacity: .2;*/ fill: none;}
.x.axis path {fill: none;}
.x.axis text {fill: #333;}
.xLabel {font-family: sans-serif; font-size: 9px;}
/* Line Chart */
/* .axis {shape-rendering: crispEdges;}
.x.axis .minor, .y.axis .minor {stroke-opacity: .5;}
.x.axis {stroke-opacity: 1;}*/
/* .y.axis line, .y.axis path, .x.axis path {fill: none; stroke: #acacac; stroke-width: 1;}
.x.axis line {stroke: #acacac; stroke-opacity: .75;}*/
/* .bigg {-webkit-transition: all .2s ease-in-out; -webkit-transform: scale(2);}
path.chartLine {stroke: #14ECC8; stroke-width: 3; fill: none;}*/
div.tooltip {position: absolute; text-align: left; padding: 4px 8px; width: auto; font-size: 10px; height: auto; background: #fff; border: 0px; pointer-events: none;}
/*circle {fill: #fff;}*/
/* Map */
.leaflet-popup-content {font-family: Merriweather;}
.leaflet-popup-content h2 {margin-bottom: 4px;}
img.petThumbs {height: 80px; width: 80px; border-radius: 1000px;}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

View File

@ -1,17 +1,13 @@
<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/sheetsee.js'></script>
<link rel="shortcut icon" href="favicon.png"/>
<script type="text/javascript" src='js/mustache.js'></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link href='http://api.tiles.mapbox.com/mapbox.js/v1.4.0/mapbox.css' rel='stylesheet' />
<link rel='stylesheet' type='text/css' href='http://fonts.googleapis.com/css?family=Lato:300,400,700,300italic'>
<link rel='stylesheet' type='text/css' href='http://fonts.googleapis.com/css?family=Amatic+SC:400,700'>
<link media="screen" rel="stylesheet" type="text/css" href="css/style.css">
<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">
</head>
<body>
@ -19,179 +15,179 @@
<h1>NYC Bookstores</h1>
<div>
<ul class="nav">
<li><strong>The Many Bookstores of New York City</strong></li>
<li><a href="#info">INFO</a> -</li>
<li><a href="http://www.github.com/deltamualpha/nyc-bookstores" target="_blank">GITHUB</a> -</li>
<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="rightSide">
<div id="latestSpot"></div>
<div id="selectedSpot"></div>
</div>
<div id="map"></div>
</div>
<div id="info" 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>. Powered by <a href="http://jlord.github.com/sheetsee.js" target="_blank">sheetsee.js</a>; based on a project by <a href="http://www.twitter.com/jllord" target="_blank">@jllord</a>.
<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">
<input id="tableFilter" type="text" placeholder="filter by.."></input>
<span class="clear button">Clear</span> <span class="resetMap button">Reset Map</span>
<span class="noMatches">no matches</span>
<div id="hackSpotsTable"></div>
<div id="Stores"></div>
</div>
</div><!-- end wrapper -->
<script id="hackSpotsTable" type="text/html">
<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}} <a href="https://maps.google.com/maps?q={{name}} {{address}},{{city}},NY" target="_blank">&#x2197;</a></td></tr>
<tr id="{{rowNumber}}" class="spotRow">
<td>{{name}}</td>
<td>{{address}}, {{city}}</td>
</tr>
{{/rows}}
</table>
</script>
<script id="latestSpot" type="text/html">
{{#rows}}
<h4 class="fauxButton">MOST RECENTLY ADDED</h4>
<script id="selectedStore" type="text/html">
{{#store}}
<h2>{{name}}</h2>
<p class="colorText">{{address}}<p>
<p class="colorText">{{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>
<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="category">Events:</span> {{events}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="category">Caf&eacute;:</span> {{cafe}}</li>
<li>
<span class="category">Events:</span> {{events}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="category">Caf&eacute;:</span> {{cafe}}
</li>
<li><span class="category">Website:</span> <a href='{{website}}' target="_blank">{{website}}</a></li>
</ul>
{{#description}}<ul>
<li class="description">{{description}}</li>
</ul>{{/description}}
{{/rows}}
{{#description}}
<p class="description">{{description}}</p>
{{/description}}
{{/store}}
</script>
<script id="theNumberofSpots" type="text/html">
<p><strong><span class="red-text">{{numberOfSpots}}</span> bookstores mapped!</p>
</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
});
<script id="selectedSpot" type="text/html">
{{#rows}}
<h4 class="fauxButton">SELECTED BOOKSTORE</h4>
<h2>{{name}}</h2>
<p class="colorText">{{address}}<p>
<p class="colorText">{{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="category">Events:</span> {{events}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="category">Caf&eacute;:</span> {{cafe}}</li>
<li><span class="category">Website:</span> <a href='{{website}}' target="_blank">{{website}}</a></li>
</ul>
{{#description}}<ul>
<li class="description">{{description}}</li>
</ul>{{/description}}
{{/rows}}
</script>
var popup = new mapboxgl.Popup({
closeOnClick: false,
closeButton: false
});
<script type="text/javascript">
function showInfo(gData) {
var tableData = gData.slice(0).sort(
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);
});
});
var tableOptions = {
'data': tableData,
'tableDiv': '#hackSpotsTable',
'filterDiv': '#tableFilter'
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) {
var geometry = store.geometry ? store.geometry.coordinates : [store.long, store.lat];
var properties = store.properties ? store.properties : store;
map.flyTo({center: geometry});
popup.setLngLat(geometry)
.setHTML(properties.name)
.addTo(map);
$('#info').hide();
var template = $('#selectedStore').html();
var rendered = Mustache.render(template, {store: properties});
$('#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.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);
}
});
// 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);
};
// make the table, and the search bar
Sheetsee.makeTable(tableOptions);
Sheetsee.initiateTableFilter(tableOptions);
// create geoJSON with coordinates and other
// useful bits from the original data
var optionsJSON = ['name', 'address', 'city', 'rowNumber'];
var geoJSON = Sheetsee.createGeoJSON(gData, optionsJSON);
// create map, tilelayer (map background), markers and popups
var map = Sheetsee.loadMap('map');
Sheetsee.addTileLayer(map, 'jllord.n7aml2bc');
var markerLayer = Sheetsee.addMarkerLayer(geoJSON, map, '<h2>{{ name }}</h2>');
var theLatestSpot = gData[gData.length - 1];
var latestSpot = Sheetsee.ich.latestSpot({
rows: theLatestSpot
});
// set it and pan to it
$('#latestSpot').html(latestSpot);
map.setView([theLatestSpot.lat, theLatestSpot.long], 14);
// when someone clicks on a row, highlight it and re-center the map
$('.spotRow').live('click', function() {
$('.spotRow').removeClass('selectedRow');
var rowNumber = $(this).closest('tr').attr('id');
$('#' + rowNumber).addClass('selectedRow');
var dataElement = Sheetsee.getMatches(gData, rowNumber, 'rowNumber');
var selectedSpot = Sheetsee.ich.selectedSpot({ rows: dataElement });
$('#latestSpot').css('display', 'none');
$('#selectedSpot').html(selectedSpot).css('display', 'inline');
var selectedCoords = [dataElement[0].lat, dataElement[0].long];
map.setView(selectedCoords, 14);
});
// Add click listener to the markerLayer
markerLayer.on('click', function(e) {
// clear any selected rows
$('.spotRow').removeClass('selectedRow');
// get row number of selected marker
var rowNumber = e.layer.feature.opts.rowNumber;
// find that row in the table and make consider it selected
$('#' + rowNumber).addClass('selectedRow');
// using row number, get the data for the selected spot
var dataElement = Sheetsee.getMatches(gData, rowNumber.toString(), 'rowNumber');
// take those details and re-write the selected spot section
var selectedSpot = Sheetsee.ich.selectedSpot({ rows: dataElement });
// center the map on the selected element
map.panTo([dataElement[0].lat, dataElement[0].long]);
// update the spot listing
$('#latestSpot').css('display', 'none');
$('#selectedSpot').html(selectedSpot).css('display', 'inline');
});
// reset the map, zoom out, and recenter on 0,0
$('.resetMap').click(function() {
$('.spotRow').removeClass('selectedRow');
$('#latestSpot').css('display', 'inline');
$('#selectedSpot').css('display', 'none');
map.setView([0, 0], 1);
});
// find total number of spots added
$('#theNumberofSpots').html(Sheetsee.ich.theNumberofSpots({ numberOfSpots: gData.length }));
if (window.location.hash) {
$('#tableFilter').val(window.location.hash.substring(1)).keyup();
$('.spotRow').first().click();
}
}
document.addEventListener('DOMContentLoaded', function() {
$.getJSON('./stores.json', function(data) {
$.each(data, function(key, value) { value.rowNumber = key; });
showInfo(data);
});
});
$(document).on('keyup', '#tableFilter', function() {
window.location.hash = $(this).val();
$('.spotRow').first().click();
});
</script>
</body>
</html>

6
js/jquery.js vendored

File diff suppressed because one or more lines are too long

1
js/mustache.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,14 @@
# Hi License!
Copyright (c) 2017, David Ashby
All rights reserved.
## This repo is BSD licensed.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistribution and use of this software in source and binary forms, with or
without modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of Yahoo! Inc. nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of Yahoo! Inc.
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -26,7 +16,11 @@ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.

View File

@ -1,35 +1 @@
# Hi!
![screenshot](https://raw.github.com/jlord/hack-spots/gh-pages/img/hackspotsss.png)
This is the code for a website that lists bookstores in New York City!
### Fork -n- Go!
Here's a fun fact:
GitHub gives free hosting for every repository (see [GitHub Pages](http://pages.github.com)).
This repo only has a **gh-pages** branch, the branch GitHub hosts, which means as soon as you **fork** it, you have a hosted and live version of it yourself! Read more about [fork-n-go](http://jlord.github.io/forkngo) type of projects.
Next, create a spreadsheet with the same column headers as [the original](https://docs.google.com/a/github.com/spreadsheets/d/1hnfQcggYcBYimuO_UOMvwoOi_I9vUvFpkMt4wjrrpLE/edit#gid=0).
Click on the `index.html` file, click edit and change **line 118** (or thereabouts) it looks like:
```javascript
document.addEventListener('DOMContentLoaded', function() {
var gData
var URL = "0Ao5u1U6KYND7dFVkcnJRNUtHWUNKamxoRGg4ZzNiT3c"
Tabletop.init( { key: URL, callback: showInfo, simpleSheet: true } )
})
```
Replace the existing spreadsheet URL key with your spreadsheet's key. You'll find that by clicking (in Google Spreadsheets) File > Publish to the Web > Start Publishing, it will then display the key in a window. ![get key](https://raw.github.com/jllord/sheetsee-cache/master/img/key.png)
Commit those changes and **LIKE WOAH** you now have a version of this website hooked to a spreadsheet that you can distrubute however you'd like.
You can find your version at **yourGitHubName.github.io/theReposName** (in this case /hack-spots).
## But How?
A Google Spreadsheet holds all the data and it is connected to this website using the goodies in [sheetsee.js](http://www.github.com/jlord/sheetsee.js). Everytime you visit the website, you'll have the most up to date data that has been entered into the spreadsheet.
This is the code for a website that lists bookstores in New York City.

View File

@ -11,8 +11,7 @@
"country": "USA",
"website": "http://www.housingworks.org/bookstore/",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "McNally Jackson Books",
@ -26,8 +25,7 @@
"country": "USA",
"website": "http://www.mcnallyjackson.com/",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "Word Bookstore",
@ -41,8 +39,7 @@
"country": "USA",
"website": "http://www.wordbookstores.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Astoria Bookshop",
@ -56,8 +53,7 @@
"country": "USA",
"website": "http://www.astoriabookshop.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Enigma Bookstore",
@ -71,8 +67,7 @@
"country": "USA",
"website": "https://www.facebook.com/pages/Enigma-Bookstore/138243176369174",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "PowerHouse Arena",
@ -86,8 +81,7 @@
"country": "USA",
"website": "http://www.powerhousearena.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Mercer Street Books & Records",
@ -101,8 +95,7 @@
"country": "USA",
"website": "http://www.mercerstreetbooks.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Mast Books",
@ -116,8 +109,7 @@
"country": "USA",
"website": "http://www.mastbooks.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "The Mysterious Bookshop",
@ -131,8 +123,7 @@
"country": "USA",
"website": "http://www.mysteriousbookshop.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Bookmarc",
@ -146,8 +137,7 @@
"country": "USA",
"website": "https://www.marcjacobs.com/bookmarc/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Singularity&Co.",
@ -161,8 +151,7 @@
"country": "USA",
"website": "http://singularityshop.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Ursus Books",
@ -176,8 +165,7 @@
"country": "USA",
"website": "http://www.ursusbooks.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Alabaster Bookshop",
@ -191,8 +179,7 @@
"country": "USA",
"website": "",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Unnameable Books",
@ -206,8 +193,7 @@
"country": "USA",
"website": "http://unnameablebooks.blogspot.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Community Bookstore",
@ -221,8 +207,7 @@
"country": "USA",
"website": "http://communitybookstore.net/",
"events": "",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Greenlight Bookstore",
@ -236,8 +221,7 @@
"country": "USA",
"website": "http://greenlightbookstore.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "P.S. Bookshop",
@ -251,8 +235,7 @@
"country": "USA",
"website": "http://www.psbnyc.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Loft Book Store Cafe",
@ -266,8 +249,7 @@
"country": "USA",
"website": "http://loft-book-store-cafe.blogspot.com/",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "Dashwood Books",
@ -281,8 +263,7 @@
"country": "USA",
"website": "http://www.dashwoodbooks.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Molasses Books",
@ -296,8 +277,7 @@
"country": "USA",
"website": "https://www.facebook.com/MolassesBooks",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "The Corner Bookstore",
@ -311,8 +291,7 @@
"country": "USA",
"website": "http://cornerbookstorenyc.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "East Village Books",
@ -326,8 +305,7 @@
"country": "USA",
"website": "http://www.buyusedbooksnewyork.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Strand Bookstore",
@ -341,8 +319,7 @@
"country": "USA",
"website": "http://www.strandbooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Bluestockings",
@ -356,8 +333,7 @@
"country": "USA",
"website": "http://bluestockings.com/",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "Kinokunya",
@ -371,8 +347,7 @@
"country": "USA",
"website": "http://www.kinokuniya.com/us/",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "Bankstreet Bookstore",
@ -386,8 +361,7 @@
"country": "USA",
"website": "http://www.bankstreetbooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Unoppressive Non-Imperialist Bargain Books",
@ -401,8 +375,7 @@
"country": "USA",
"website": "http://unoppressivebooks.blogspot.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Three Lives & Company",
@ -416,8 +389,7 @@
"country": "USA",
"website": "http://www.threelives.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Shakespeare & Company",
@ -431,8 +403,7 @@
"country": "USA",
"website": "http://www.shakeandco.com/",
"events": "No",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "Book Culture",
@ -446,8 +417,7 @@
"country": "USA",
"website": "http://www.bookculture.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Book Culture on Broadway",
@ -461,8 +431,7 @@
"country": "USA",
"website": "http://www.bookculture.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "bookbook",
@ -476,8 +445,7 @@
"country": "USA",
"website": "http://bookbooknyc.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Westsider Rare & Used Books",
@ -491,8 +459,7 @@
"country": "USA",
"website": "http://westsiderbooks.com/bookstore.html",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Word Up Books",
@ -506,8 +473,7 @@
"country": "USA",
"website": "http://wordupbooks.wordpress.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Turn The Page... Again",
@ -521,8 +487,7 @@
"country": "USA",
"website": "http://www.turnthepageagain.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Book Thug Nation",
@ -536,8 +501,7 @@
"country": "USA",
"website": "http://www.bookthugnation.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Idlewild Books Manhattan",
@ -551,8 +515,7 @@
"country": "USA",
"website": "http://www.idlewildbooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Idlewild Books Brooklyn",
@ -566,8 +529,7 @@
"country": "USA",
"website": "http://www.idlewildbooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Idlewild Books Williamsburg",
@ -581,8 +543,7 @@
"country": "USA",
"website": "http://www.idlewildbooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Posman Books Chelsea Market",
@ -596,8 +557,7 @@
"country": "USA",
"website": "http://posmanbooks.com/our-stores/chelsea-market/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Posman Books Rockefeller Center",
@ -611,8 +571,7 @@
"country": "USA",
"website": "http://posmanbooks.com/our-stores/rockefeller-center/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Books Of Wonder",
@ -626,8 +585,7 @@
"country": "USA",
"website": "http://www.booksofwonder.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Bonnie Slotnick Cookbooks",
@ -641,8 +599,7 @@
"country": "USA",
"website": "http://www.bonnieslotnickcookbooks.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Kitchen Arts & Letters",
@ -656,8 +613,7 @@
"country": "USA",
"website": "http://kitchenartsandletters.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Revolution Books",
@ -671,8 +627,7 @@
"country": "USA",
"website": "http://www.revolutionbooksnyc.org/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Spoonbill & Sugartown, Booksellers",
@ -686,8 +641,7 @@
"country": "USA",
"website": "http://www.spoonbillbooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Melville House Publishers",
@ -701,8 +655,7 @@
"country": "USA",
"website": "http://www.mhpbooks.com/about/the-melville-house-bookstore-2/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Printed Matter",
@ -716,8 +669,7 @@
"country": "USA",
"website": "http://printedmatter.org/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "192 Books",
@ -731,8 +683,7 @@
"country": "USA",
"website": "http://www.192books.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Freebird Books",
@ -746,8 +697,7 @@
"country": "USA",
"website": "http://www.freebirdbooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Berl's Brooklyn Poetry Shop",
@ -761,8 +711,7 @@
"country": "USA",
"website": "http://www.berlspoetry.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Hullabaloo Books",
@ -776,8 +725,7 @@
"country": "USA",
"website": "https://www.facebook.com/HullabalooBooks",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Here's A Book Store",
@ -791,8 +739,7 @@
"country": "USA",
"website": "https://www.facebook.com/pages/Heres-A-Book-Store/115732881789797",
"events": "?",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Argosy Books",
@ -806,8 +753,7 @@
"country": "USA",
"website": "http://www.argosybooks.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Black Sea Book Store",
@ -821,8 +767,7 @@
"country": "USA",
"website": "",
"events": "?",
"cafe": "?",
"hexcolor": "#B9FCFC"
"cafe": "?"
},
{
"name": "PowerHouse on 8th",
@ -836,8 +781,7 @@
"country": "USA",
"website": "http://powerhouseon8th.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Terrace Books",
@ -851,8 +795,7 @@
"country": "USA",
"website": "http://terracebooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "BookMark Shoppe",
@ -866,8 +809,7 @@
"country": "USA",
"website": "http://www.bookmarkshoppe.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Boulevard Books and Café",
@ -881,8 +823,7 @@
"country": "USA",
"website": "https://www.facebook.com/BoulevardBooksandCafe",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "Better Read Than Dead",
@ -896,8 +837,7 @@
"country": "USA",
"website": "",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Civil Service Book Shop",
@ -911,8 +851,7 @@
"country": "USA",
"website": "",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Desert Island Comics",
@ -926,8 +865,7 @@
"country": "USA",
"website": "http://desertislandbrooklyn.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "La Casa Azul Bookstore",
@ -941,8 +879,7 @@
"country": "USA",
"website": "http://www.lacasaazulbookstore.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Topos Bookstore Cafe",
@ -956,8 +893,7 @@
"country": "USA",
"website": "http://toposbookstore.com/",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "Human Relations Books",
@ -971,8 +907,7 @@
"country": "USA",
"website": "http://www.humanrelationsbooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Respect For Life Books-N-Things",
@ -986,8 +921,7 @@
"country": "USA",
"website": "",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Every Thing Goes Book Cafe and Neighborhood Stage",
@ -1001,8 +935,7 @@
"country": "USA",
"website": "http://www.etgstores.com/bookcafe/",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "The Center for Fiction",
@ -1016,8 +949,7 @@
"country": "USA",
"website": "http://www.centerforfiction.org/about/the-center-bookshop/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "The Drama Book Shop",
@ -1031,8 +963,7 @@
"country": "USA",
"website": "http://www.dramabookshop.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Catland",
@ -1046,8 +977,7 @@
"country": "USA",
"website": "http://www.catlandbooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Logos Bookstore",
@ -1061,8 +991,7 @@
"country": "USA",
"website": "http://www.logosbookstorenyc.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Pioneer Books",
@ -1076,8 +1005,7 @@
"country": "USA",
"website": "http://pioneerworks.org/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Joanne Hendricks Cookbooks",
@ -1091,8 +1019,7 @@
"country": "USA",
"website": "http://joannehendrickscookbooks.com/",
"events": "No",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Sister's Uptown Bookstore",
@ -1106,8 +1033,7 @@
"country": "USA",
"website": "http://www.sistersuptownbookstore.com//",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "Stories",
@ -1121,8 +1047,7 @@
"country": "USA",
"website": "http://storiesbk.com/bookshop/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Archestratus",
@ -1136,8 +1061,7 @@
"country": "USA",
"website": "https://www.archestrat.us/",
"events": "Yes",
"cafe": "Yes",
"hexcolor": "#B9FCFC"
"cafe": "Yes"
},
{
"name": "Quest Bookshop",
@ -1151,8 +1075,7 @@
"country": "USA",
"website": "http://www.questbookshop.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "The Austin Book Shop",
@ -1166,8 +1089,7 @@
"country": "USA",
"website": "https://www.facebook.com/The-Austin-Book-Shop-177311612281452/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Ben's Books",
@ -1181,8 +1103,7 @@
"country": "USA",
"website": "http://bensbooks.nyc/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "The Book Cellar",
@ -1196,8 +1117,7 @@
"country": "USA",
"website": "http://www.angelfire.com/trek/tothecellar/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
},
{
"name": "Chartwell Booksellers",
@ -1211,7 +1131,6 @@
"country": "USA",
"website": "http://www.churchillbooks.com/",
"events": "Yes",
"cafe": "No",
"hexcolor": "#B9FCFC"
"cafe": "No"
}
]