From b083d0cb30d5cf711d15c2a76ea2e95a289b3b32 Mon Sep 17 00:00:00 2001 From: Jessica Lord Date: Fri, 5 Sep 2014 16:12:39 -0700 Subject: [PATCH 01/13] switch to new spreadsheet --- index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.html b/index.html index 06ab10f..2cf9704 100644 --- a/index.html +++ b/index.html @@ -122,8 +122,7 @@ From 98f00eaf24690c8fb9264d0a86a3dfc5a0dd8558 Mon Sep 17 00:00:00 2001 From: David Ashby Date: Sat, 7 Mar 2015 18:47:16 -0500 Subject: [PATCH 09/13] hoist gData onto window so other functions can use it --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index bd3d4eb..4b13cae 100644 --- a/index.html +++ b/index.html @@ -130,7 +130,7 @@ // so long, so messy function showInfo(gData) { - gData + window.gData = gData // make the table, and the search bar Sheetsee.makeTable(gData, "#hackSpotsTable") Sheetsee.initiateTableFilter(gData, "#tableFilter", "#hackSpotsTable") From 62d257957b73d42bd008ca89d66035f22bcc74b5 Mon Sep 17 00:00:00 2001 From: David Ashby Date: Sat, 7 Mar 2015 22:02:36 -0500 Subject: [PATCH 10/13] this at least makes things render... --- index.html | 28 +- js/ICanHaz.js | 542 -- js/sheetsee.js | 16574 +++++++++++++++++++++++++++++++++++++++++++++-- js/site.js | 0 4 files changed, 16107 insertions(+), 1037 deletions(-) delete mode 100644 js/ICanHaz.js delete mode 100644 js/site.js diff --git a/index.html b/index.html index 4b13cae..ea14050 100644 --- a/index.html +++ b/index.html @@ -2,8 +2,6 @@ Hack Spots - - @@ -64,7 +62,6 @@ NameAddressCityStateCountryElsewhere {{#rows}} {{name}}{{address}}{{city}}{{state}}{{country}}G Map Yelp - wifi: {{wifipassword}} {{/rows}} @@ -131,9 +128,14 @@ function showInfo(gData) { window.gData = gData + tableOptions = { + "data": gData, + "tableDiv": "#hackSpotsTable", + "filterDiv": "#tableFilter" + } // make the table, and the search bar - Sheetsee.makeTable(gData, "#hackSpotsTable") - Sheetsee.initiateTableFilter(gData, "#tableFilter", "#hackSpotsTable") + Sheetsee.makeTable(tableOptions) + Sheetsee.initiateTableFilter(tableOptions) // when someone clicks on a row, highlight it and // re-center the map @@ -142,14 +144,14 @@ var rowNumber = $(this).closest("tr").attr("id") $('#' + rowNumber).addClass("selectedRow") var dataElement = Sheetsee.getMatches(gData, rowNumber, "rowNumber") - var selectedSpot = ich.selectedSpot({ + 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] matchGeoJSONbyRowNumber(rowNumber, geoJSON, gData, "#FF4646") - var markerLayer = Sheetsee.addMarkerLayer(geoJSON, map, 13) + var markerLayer = Sheetsee.addMarkerLayer(geoJSON, map, "

{{ name }}

") addPopups(map, markerLayer) map.panTo(selectedCoords, 13) }) @@ -171,7 +173,7 @@ // info filled in (to prevent map breaking if // someone is currently editing spreadsheet) var theLatestSpot = findLatestCompleteSpot(gData) - var latestSpot = ich.latestSpot({ + var latestSpot = Sheetsee.ich.latestSpot({ rows: theLatestSpot }) $('#latestSpot').html(latestSpot) @@ -191,14 +193,14 @@ // create map, tilelayer (map background), markers and popups var map = Sheetsee.loadMap("map") Sheetsee.addTileLayer(map, 'examples.map-20v6611k') - var markerLayer = Sheetsee.addMarkerLayer(geoJSON, map, 13) + var markerLayer = Sheetsee.addMarkerLayer(geoJSON, map) addPopups(map, markerLayer) // design the popups to have the content and // interactions that we want function addPopups(map, markerLayer) { markerLayer.eachLayer(function(marker) { - var popupContent = ich.popUps(marker.feature.opts) + var popupContent = Sheetsee.ich.popUps(marker.feature.opts) marker.bindPopup(popupContent, {closeButton: false,}) }) markerLayer.on('click', function(e) { @@ -216,7 +218,7 @@ // using row number, get the data for the selected spot var dataElement = Sheetsee.getMatches(gData, rowNumber, "rowNumber") // take those details and re-write the selected spot section - var selectedSpot = ich.selectedSpot({ + var selectedSpot = Sheetsee.ich.selectedSpot({ rows: dataElement }) $('#latestSpot').css("display", "none") @@ -226,7 +228,7 @@ $('.resetMap').click(function() { $('.spotRow').removeClass("selectedRow") - markerLayer = Sheetsee.addMarkerLayer(geoJSON, map, 13) + markerLayer = Sheetsee.addMarkerLayer(geoJSON, map, "

{{ name }}

") addPopups(map, markerLayer) $('#latestSpot').css("display", "inline") $('#selectedSpot').css("display", "none") @@ -234,7 +236,7 @@ // find total number of spots added var numberOfSpots = gData.length - var theNumberofSpots = ich.theNumberofSpots({ + var theNumberofSpots = Sheetsee.ich.theNumberofSpots({ numberOfSpots: numberOfSpots }) $('#theNumberofSpots').html(theNumberofSpots) diff --git a/js/ICanHaz.js b/js/ICanHaz.js deleted file mode 100644 index 25a14ac..0000000 --- a/js/ICanHaz.js +++ /dev/null @@ -1,542 +0,0 @@ -/*! -ICanHaz.js version 0.10 -- by @HenrikJoreteg -More info at: http://icanhazjs.com -*/ -(function () { -/* - mustache.js — Logic-less templates in JavaScript - - See http://mustache.github.com/ for more info. -*/ - -var Mustache = function () { - var _toString = Object.prototype.toString; - - Array.isArray = Array.isArray || function (obj) { - return _toString.call(obj) == "[object Array]"; - } - - var _trim = String.prototype.trim, trim; - - if (_trim) { - trim = function (text) { - return text == null ? "" : _trim.call(text); - } - } else { - var trimLeft, trimRight; - - // IE doesn't match non-breaking spaces with \s. - if ((/\S/).test("\xA0")) { - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; - } else { - trimLeft = /^\s+/; - trimRight = /\s+$/; - } - - trim = function (text) { - return text == null ? "" : - text.toString().replace(trimLeft, "").replace(trimRight, ""); - } - } - - var escapeMap = { - "&": "&", - "<": "<", - ">": ">", - '"': '"', - "'": ''' - }; - - function escapeHTML(string) { - return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) { - return escapeMap[s] || s; - }); - } - - var regexCache = {}; - var Renderer = function () {}; - - Renderer.prototype = { - otag: "{{", - ctag: "}}", - pragmas: {}, - buffer: [], - pragmas_implemented: { - "IMPLICIT-ITERATOR": true - }, - context: {}, - - render: function (template, context, partials, in_recursion) { - // reset buffer & set context - if (!in_recursion) { - this.context = context; - this.buffer = []; // TODO: make this non-lazy - } - - // fail fast - if (!this.includes("", template)) { - if (in_recursion) { - return template; - } else { - this.send(template); - return; - } - } - - // get the pragmas together - template = this.render_pragmas(template); - - // render the template - var html = this.render_section(template, context, partials); - - // render_section did not find any sections, we still need to render the tags - if (html === false) { - html = this.render_tags(template, context, partials, in_recursion); - } - - if (in_recursion) { - return html; - } else { - this.sendLines(html); - } - }, - - /* - Sends parsed lines - */ - send: function (line) { - if (line !== "") { - this.buffer.push(line); - } - }, - - sendLines: function (text) { - if (text) { - var lines = text.split("\n"); - for (var i = 0; i < lines.length; i++) { - this.send(lines[i]); - } - } - }, - - /* - Looks for %PRAGMAS - */ - render_pragmas: function (template) { - // no pragmas - if (!this.includes("%", template)) { - return template; - } - - var that = this; - var regex = this.getCachedRegex("render_pragmas", function (otag, ctag) { - return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g"); - }); - - return template.replace(regex, function (match, pragma, options) { - if (!that.pragmas_implemented[pragma]) { - throw({message: - "This implementation of mustache doesn't understand the '" + - pragma + "' pragma"}); - } - that.pragmas[pragma] = {}; - if (options) { - var opts = options.split("="); - that.pragmas[pragma][opts[0]] = opts[1]; - } - return ""; - // ignore unknown pragmas silently - }); - }, - - /* - Tries to find a partial in the curent scope and render it - */ - render_partial: function (name, context, partials) { - name = trim(name); - if (!partials || partials[name] === undefined) { - throw({message: "unknown_partial '" + name + "'"}); - } - if (!context || typeof context[name] != "object") { - return this.render(partials[name], context, partials, true); - } - return this.render(partials[name], context[name], partials, true); - }, - - /* - Renders inverted (^) and normal (#) sections - */ - render_section: function (template, context, partials) { - if (!this.includes("#", template) && !this.includes("^", template)) { - // did not render anything, there were no sections - return false; - } - - var that = this; - - var regex = this.getCachedRegex("render_section", function (otag, ctag) { - // This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder - return new RegExp( - "^([\\s\\S]*?)" + // all the crap at the beginning that is not {{*}} ($1) - - otag + // {{ - "(\\^|\\#)\\s*(.+)\\s*" + // #foo (# == $2, foo == $3) - ctag + // }} - - "\n*([\\s\\S]*?)" + // between the tag ($2). leading newlines are dropped - - otag + // {{ - "\\/\\s*\\3\\s*" + // /foo (backreference to the opening tag). - ctag + // }} - - "\\s*([\\s\\S]*)$", // everything else in the string ($4). leading whitespace is dropped. - - "g"); - }); - - - // for each {{#foo}}{{/foo}} section do... - return template.replace(regex, function (match, before, type, name, content, after) { - // before contains only tags, no sections - var renderedBefore = before ? that.render_tags(before, context, partials, true) : "", - - // after may contain both sections and tags, so use full rendering function - renderedAfter = after ? that.render(after, context, partials, true) : "", - - // will be computed below - renderedContent, - - value = that.find(name, context); - - if (type === "^") { // inverted section - if (!value || Array.isArray(value) && value.length === 0) { - // false or empty list, render it - renderedContent = that.render(content, context, partials, true); - } else { - renderedContent = ""; - } - } else if (type === "#") { // normal section - if (Array.isArray(value)) { // Enumerable, Let's loop! - renderedContent = that.map(value, function (row) { - return that.render(content, that.create_context(row), partials, true); - }).join(""); - } else if (that.is_object(value)) { // Object, Use it as subcontext! - renderedContent = that.render(content, that.create_context(value), - partials, true); - } else if (typeof value == "function") { - // higher order section - renderedContent = value.call(context, content, function (text) { - return that.render(text, context, partials, true); - }); - } else if (value) { // boolean section - renderedContent = that.render(content, context, partials, true); - } else { - renderedContent = ""; - } - } - - return renderedBefore + renderedContent + renderedAfter; - }); - }, - - /* - Replace {{foo}} and friends with values from our view - */ - render_tags: function (template, context, partials, in_recursion) { - // tit for tat - var that = this; - - var new_regex = function () { - return that.getCachedRegex("render_tags", function (otag, ctag) { - return new RegExp(otag + "(=|!|>|&|\\{|%)?([^#\\^]+?)\\1?" + ctag + "+", "g"); - }); - }; - - var regex = new_regex(); - var tag_replace_callback = function (match, operator, name) { - switch(operator) { - case "!": // ignore comments - return ""; - case "=": // set new delimiters, rebuild the replace regexp - that.set_delimiters(name); - regex = new_regex(); - return ""; - case ">": // render partial - return that.render_partial(name, context, partials); - case "{": // the triple mustache is unescaped - case "&": // & operator is an alternative unescape method - return that.find(name, context); - default: // escape the value - return escapeHTML(that.find(name, context)); - } - }; - var lines = template.split("\n"); - for(var i = 0; i < lines.length; i++) { - lines[i] = lines[i].replace(regex, tag_replace_callback, this); - if (!in_recursion) { - this.send(lines[i]); - } - } - - if (in_recursion) { - return lines.join("\n"); - } - }, - - set_delimiters: function (delimiters) { - var dels = delimiters.split(" "); - this.otag = this.escape_regex(dels[0]); - this.ctag = this.escape_regex(dels[1]); - }, - - escape_regex: function (text) { - // thank you Simon Willison - if (!arguments.callee.sRE) { - var specials = [ - '/', '.', '*', '+', '?', '|', - '(', ')', '[', ']', '{', '}', '\\' - ]; - arguments.callee.sRE = new RegExp( - '(\\' + specials.join('|\\') + ')', 'g' - ); - } - return text.replace(arguments.callee.sRE, '\\$1'); - }, - - /* - find `name` in current `context`. That is find me a value - from the view object - */ - find: function (name, context) { - name = trim(name); - - // Checks whether a value is thruthy or false or 0 - function is_kinda_truthy(bool) { - return bool === false || bool === 0 || bool; - } - - var value; - - // check for dot notation eg. foo.bar - if (name.match(/([a-z_]+)\./ig)) { - var childValue = this.walk_context(name, context); - if (is_kinda_truthy(childValue)) { - value = childValue; - } - } else { - if (is_kinda_truthy(context[name])) { - value = context[name]; - } else if (is_kinda_truthy(this.context[name])) { - value = this.context[name]; - } - } - - if (typeof value == "function") { - return value.apply(context); - } - if (value !== undefined) { - return value; - } - // silently ignore unkown variables - return ""; - }, - - walk_context: function (name, context) { - var path = name.split('.'); - // if the var doesn't exist in current context, check the top level context - var value_context = (context[path[0]] != undefined) ? context : this.context; - var value = value_context[path.shift()]; - while (value != undefined && path.length > 0) { - value_context = value; - value = value[path.shift()]; - } - // if the value is a function, call it, binding the correct context - if (typeof value == "function") { - return value.apply(value_context); - } - return value; - }, - - // Utility methods - - /* includes tag */ - includes: function (needle, haystack) { - return haystack.indexOf(this.otag + needle) != -1; - }, - - // by @langalex, support for arrays of strings - create_context: function (_context) { - if (this.is_object(_context)) { - return _context; - } else { - var iterator = "."; - if (this.pragmas["IMPLICIT-ITERATOR"]) { - iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator; - } - var ctx = {}; - ctx[iterator] = _context; - return ctx; - } - }, - - is_object: function (a) { - return a && typeof a == "object"; - }, - - /* - Why, why, why? Because IE. Cry, cry cry. - */ - map: function (array, fn) { - if (typeof array.map == "function") { - return array.map(fn); - } else { - var r = []; - var l = array.length; - for(var i = 0; i < l; i++) { - r.push(fn(array[i])); - } - return r; - } - }, - - getCachedRegex: function (name, generator) { - var byOtag = regexCache[this.otag]; - if (!byOtag) { - byOtag = regexCache[this.otag] = {}; - } - - var byCtag = byOtag[this.ctag]; - if (!byCtag) { - byCtag = byOtag[this.ctag] = {}; - } - - var regex = byCtag[name]; - if (!regex) { - regex = byCtag[name] = generator(this.otag, this.ctag); - } - - return regex; - } - }; - - return({ - name: "mustache.js", - version: "0.4.0", - - /* - Turns a template and view into HTML - */ - to_html: function (template, view, partials, send_fun) { - var renderer = new Renderer(); - if (send_fun) { - renderer.send = send_fun; - } - renderer.render(template, view || {}, partials); - if (!send_fun) { - return renderer.buffer.join("\n"); - } - } - }); -}(); -/*! - ICanHaz.js -- by @HenrikJoreteg -*/ -/*global */ -(function () { - function trim(stuff) { - if (''.trim) return stuff.trim(); - else return stuff.replace(/^\s+/, '').replace(/\s+$/, ''); - } - var ich = { - VERSION: "0.10", - templates: {}, - - // grab jquery or zepto if it's there - $: (typeof window !== 'undefined') ? window.jQuery || window.Zepto || null : null, - - // public function for adding templates - // can take a name and template string arguments - // or can take an object with name/template pairs - // We're enforcing uniqueness to avoid accidental template overwrites. - // If you want a different template, it should have a different name. - addTemplate: function (name, templateString) { - if (typeof name === 'object') { - for (var template in name) { - this.addTemplate(template, name[template]); - } - return; - } - if (ich[name]) { - console.error("Invalid name: " + name + "."); - } else if (ich.templates[name]) { - console.error("Template \"" + name + " \" exists"); - } else { - ich.templates[name] = templateString; - ich[name] = function (data, raw) { - data = data || {}; - var result = Mustache.to_html(ich.templates[name], data, ich.templates); - return (ich.$ && !raw) ? ich.$(result) : result; - }; - } - }, - - // clears all retrieval functions and empties cache - clearAll: function () { - for (var key in ich.templates) { - delete ich[key]; - } - ich.templates = {}; - }, - - // clears/grabs - refresh: function () { - ich.clearAll(); - ich.grabTemplates(); - }, - - // grabs templates from the DOM and caches them. - // Loop through and add templates. - // Whitespace at beginning and end of all templates inside - - - - + + Hack Spots + + + + + + - - - - - - - - - + + + + + + + + + -
-

Hack Spots

-
- -
-
-
-
-
-
-
-
-
- - Clear Reset Map - no matches -
-
-
-

Contribute!

-
-

This website is hooked up to this Google Spreadsheet, which I've shared, so click and add your favorite hack spots to the bottom of the list! For the map you'll need to get the lat and long of the spot, you can get that here. The locating of these places is helpful, so please try to fill out all the columns.

+
+

Hack Spots

+
+ +
+
+
+
+
+
+
+
+
+ + Clear Reset Map + no matches +
+
+
+

Contribute!

+
+

This website is hooked up to this Google Spreadsheet, which I've shared, so click and add your favorite hack spots to the bottom of the list! For the map you'll need to get the lat and long of the spot, you can get that here. The locating of these places is helpful, so please try to fill out all the columns.

-

Info

-

When I'm visiting a new city I'd like to know which coffee shops have the best vibes, great coffee and are good for hunkering down and having a good hack. Yelp will tell you where the Starbucks is and Foursquare will tell you where your friend's have been - but did they like it and was it a grab in go place or a hack place? Plus, what about the people I don't follow on Foursquare or who can't check-in when in other countries?

+

Info

+

When I'm visiting a new city I'd like to know which coffee shops have the best vibes, great coffee and are good for hunkering down and having a good hack. Yelp will tell you where the Starbucks is and Foursquare will tell you where your friend's have been - but did they like it and was it a grab in go place or a hack place? Plus, what about the people I don't follow on Foursquare or who can't check-in when in other countries?

-

Besides being a list I've wanted to have, it's a fantastic (or I think so) way of using sheetsee.js, which is a little JavaScript library I've been working on. Sheetsee.js helps you hook a Google Spreadsheet (awesome for data and collaboration!) to a website to make data more visual (maps, tables, charts).

+

Besides being a list I've wanted to have, it's a fantastic (or I think so) way of using sheetsee.js, which is a little JavaScript library I've been working on. Sheetsee.js helps you hook a Google Spreadsheet (awesome for data and collaboration!) to a website to make data more visual (maps, tables, charts).

-

Fork-n-Go

-

This is a work-in-progress example of a fork-n-go project - which means, there is just a gh-pages branch in GitHub for this project so when you fork it, you've got a live and hosted website instantly. BAM! Just copy the spreadsheet headers and create your own spreadsheet, swap out the spreadsheet key in index.html and commit those changes. BAM! You've got a live and hosted site with a spreadsheet you control. More on the readme.

-
-
+

Fork-n-Go

+

This is a work-in-progress example of a fork-n-go project - which means, there is just a gh-pages branch in GitHub for this project so when you fork it, you've got a live and hosted website instantly. BAM! Just copy the spreadsheet headers and create your own spreadsheet, swap out the spreadsheet key in index.html and commit those changes. BAM! You've got a live and hosted site with a spreadsheet you control. More on the readme.

+
+
- + - + - + - + - + - + function matchGeoJSONbyRowNumber(rowNumber, geoJSON, gdata, highlightColor) { + geoJSON.forEach(function (d) { + if (d.properties["marker-color"] === highlightColor) { + var origColor = gData[0].hexcolor + d.properties["marker-color"] = origColor + } + for (var key in d.opts) { + var value = d.opts[key].toString().toLowerCase() + if (key === 'rowNumber' && value.match(rowNumber.toString().toLowerCase())) { + d.properties["marker-color"] = highlightColor + return geoJSON + } + } + }) + } + } + From 89cc46c905e137bb17109904e9768e8a419f52ac Mon Sep 17 00:00:00 2001 From: David Ashby Date: Sun, 8 Mar 2015 23:48:56 -0400 Subject: [PATCH 12/13] finish modifications to work with newest sheetsee.js This removes the color-changing on click for markers, which... eh. I can't figure out a clean way to re-render the Marker Layer. (Calling .addMarkerLayer just layers a new one over the old one.) --- index.html | 129 +++++++++++++++++++---------------------------------- 1 file changed, 46 insertions(+), 83 deletions(-) diff --git a/index.html b/index.html index a1b7471..2655dea 100644 --- a/index.html +++ b/index.html @@ -92,10 +92,6 @@

{{numberOfSpots}} hack spots strong!

- - From 6605cc4e6e9c437475784e2bf241c136a46c2235 Mon Sep 17 00:00:00 2001 From: David Ashby Date: Mon, 9 Mar 2015 00:26:47 -0400 Subject: [PATCH 13/13] we don't actually need to do this anymore! --- index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/index.html b/index.html index 2655dea..f0a821b 100644 --- a/index.html +++ b/index.html @@ -122,7 +122,6 @@ // so long, so messy function showInfo(gData) { - window.gData = gData tableOptions = { "data": gData, "tableDiv": "#hackSpotsTable",