diff --git a/changelog.md b/changelog.md deleted file mode 100644 index 6aba04ae..00000000 --- a/changelog.md +++ /dev/null @@ -1,22 +0,0 @@ -## August 13, 2013 -### Charting Intake - -D3 charts need an array of objects, and something to chart: the thing itself (aka labels) and the corresponding value (aka units). Your data usually contains more than D3 needs to make the chart, so you have to tell it what to chart from your data to chart. - -Previously Sheetsee required you pass your data through a function, `addUnitsAndLabels()` which took in your data and the things you wanted to chart, reformatted your data for you so that you could pass it into one of the d3 charts. This is one more step than actually needs to happen. - -Now Sheetsee just asks for what you want your _labels_ and _units_ to be in the options you give it when calling the chart function. It then sorts the data correctly on the inside of the chart function. Yay, easier! - -``` - var options = { - labels: "name", - units: "cuddleability", - m: [60, 60, 30, 150], - w: 600, h: 400, - div: "#barChart", - xaxis: "no. of pennies", - hiColor: "#FF317D" - } -``` - -Thanks @maxogden for the help with this. diff --git a/css/site.css b/css/site.css deleted file mode 100644 index f12e0489..00000000 --- a/css/site.css +++ /dev/null @@ -1,90 +0,0 @@ -/* Page Specific CSS */ - -body {font-family: Merriweather; background: #fff; color: #333; font-size: 100%; border: 10px #47CCFC solid; margin: 0px; padding: 20px 20px 200px 20px; font-size: 16px; } -h1, h2, h3, h4, h5, h6 {font-family: Helvetica, Arial, sans-serif;} -h2 {margin-top: 82px;} - -h3.functionH {margin-left: -14px; margin-top: 52px; border-top: 3px solid #47CCFC; border-left: 3px solid #47CCFC; border-right: 3px solid #47CCFC; padding-left: 14px; padding-top: 9px; } -img {width: 100%;} - -p a, a {color: #333; text-decoration: none; padding-bottom: 0px; border-bottom: 2px #CCF4FF solid;} -p a:visted {color: #ff00ff;} -a:hover {color: #47CCFC;} -a:visited {color: #333;} -small {padding: 10px 0px;} -p, ol {line-height: 24px;} - -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;} - -/* funsies */ -::selection {background: #44FFB4;} -::-moz-selection {background: #44FFB4;} - -img.petThumbs {height: 80px; width: 80px; border-radius: 1000px;} - -.button {padding: 5px 4px; background-color: #fff; font-size: 10px;} - -#menu {color: #fff; padding: 20px; float: left; position: fixed; left: 40px; top: 40px; max-width: 300px; font-family: Helvetica, Arial, sans-serif; font-size: 14px;} -#menu ul {list-style: none; margin: 0px; padding: 0px;} -#menu li {line-height: 34px;} -#menu li a {padding: 4px 8px; background-color: #F0F0F0; text-decoration: none; border: none;} -#menu li a.a2 {background-color: #CCF4FF;} -#menu li a:hover {background-color: #e7e7e7; color: #333;} - -#wrapper {margin: 0px auto; max-width: 800px; padding-top: 40px;} - -/* Examples */ -.ssExample {margin: 20px -28px; background-color: #CCF4FF; padding: 20px 28px; background-color: #CCF4FF; border: 8px solid #47CCFC; margin-top: 44px; padding-top: 0px; overflow: auto;} -.ssExample li {padding: 2px 0px;} -.ssExample h2 {margin-top: inherit;} - -/* Table */ -.ssExample table {min-width: 600px;} -.tHeader::after {content: " \2193 \2191 "; font-size: 10px; padding-left: 3px;} - -/* Map Popup Style */ -.leaflet-popup-content h2 {margin-bottom: 4px; margin-top: auto; font-family: Merriweather;} - -/* Most Cuddleable Template */ -#mostCuddle img.most {max-width: 400px; border-radius: 9999px; margin-top: 34px;} -#mostCuddle {text-align: center;} -#mostCuddle table {width: auto;} -#mostCuddle li {padding: 10px 0px; font-size: 18px; display: inline-block;} -.boxText {background-color: #47CCFC; padding: 4px 8px; font-family: Helvetica, Arial, sans-serif;} - -/* Bar Chart */ -#dogBar.labels text {text-align: right;} -#dogBar.bar .labels text {fill: #333;} -#dogBar.bar rect {fill: #e6e6e6;} -#dogBar.axis {shape-rendering: crispEdges;} -#dogBar .x.axis line {stroke: #CCF4FF; fill: none;} -#dogBar.x.axis path {fill: none;} -#dogBar.x.axis text {fill: #333;} -#dogBar.xLabel {font-family: sans-serif; font-size: 9px;} - - -/* Line Chart */ -#dogLine.axis {shape-rendering: crispEdges;} -#dogLine.x.axis .minor, #dogLine.y.axis .minor {stroke-opacity: .5;} -#dogLine.x.axis {stroke-opacity: 1;} -#dogLine.y.axis line, #dogLine.y.axis path, #dogLine.x.axis path {fill: none; stroke: #acacac; stroke-width: 1;} -#dogLine .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;} - -/* Pie Chart */ -.arc path { stroke: #fff;} - -/* Responsive Town */ - -@media only screen and (-webkit-min-device-pixel-ratio: 2) and (min-width: 320px) and (max-width: 1024px) { - body {padding-bottom: 50px;} - #wrapper {max-width: 100%; padding-top: 20px;} - #menu {color: #fff; padding: 0px; float: none; position: relative; left: auto; top: auto; max-width: 100%; font-family: Helvetica, Arial, sans-serif;} - #menu li {display: inline-block;} - h3.functionH {margin: 0px; border-top: 5px solid #47CCFC; border-left: 0px; border-right: 0px; padding-top: 9px; word-wrap: break-word; padding-left: 0px;} - ul {padding-left: 20px;} -} diff --git a/css/style.css b/css/style.css deleted file mode 100644 index b0e42642..00000000 --- a/css/style.css +++ /dev/null @@ -1,56 +0,0 @@ - /* General */ - - body {margin: 0px auto;} - a {color: #333;} - #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 20px 3px 0px; font-size: 14px;} - #tableFilter, #basicFilter, #dogFilter {margin: 12px 0px; border: none; border-bottom: 1px solid #333; background-color: transparent; padding: 0px; font-family: Merriweather; color: #FCB688; font-size: 13px; height: 22px;} - .tHeader {/* table column header style */} - .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; overflow: hidden;} - #holder {height: 400px; max-width: 600px; background: #FFE4E4;} - - /* Overflow for large tables and chart */ - .container {overflow-x: auto;} - #yourDiv {min-width: 600px} - - /* Bar Chart */ - - .labels text {text-align: right;} - .bar .labels text {fill: #333;} - .bar rect {fill: #e6e6e6;} - .axis {shape-rendering: crispEdges;} - .x.axis line {stroke: #fff; 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 {fill: none; stroke: #acacac; stroke-width: 1;} - .bigg {-webkit-transition: all .2s ease-in-out; -webkit-transform: scale(2);} - path.chartLine {stroke: #333; 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: #e6e6e6;} - -/* Map */ - - .leaflet-popup-content {} - - @media only screen and (-webkit-min-device-pixel-ratio: 2) and (min-width: 320px) and (max-width: 1024px) { - -} diff --git a/demo.html b/demo.html deleted file mode 100644 index 7c07a7d5..00000000 --- a/demo.html +++ /dev/null @@ -1,503 +0,0 @@ - - - Yo, yo, yo! - - - - - - - - - - - - - - - - - -
-

sheetsee

-

Sheetsee.js

-

Sheetsee.js is a JavaScript library, or box of goodies, if you will, that makes it easy to use a Google Spreadsheet as the database feeding the tables, charts and maps on a website. Once set up, any changes to the spreadsheet will auto-saved by Google and be live on your site when a visitor refreshes the page.

-

Using Google Spreadsheets as the backend database is awesome because it is easy to use, share and collaborate with.

-

To use sheetsee.js you'll definitely need to know HTML, CSS and know JavaScript or be not afraid of it and just type what these docs tell you to type. Also, see JavaScript for Cats, Eloquent JavaScript or Mozilla's Developer Network.

- -

Dependencies

-

Sheetsee.js depends on a few other awesome JavaScript libraries to make all this happen. First, Tabletop.js gets the data from the Google Spreadsheet and makes it nice. Once you have your data Sheetsee.js makes it easy to set up tables or templates with IChanHas.js (built on mustache.js), maps with Mapbox.js, and charts with d3.js. And jQuery of course powers most of the interactions. It also has many sorting and filtering functions built in so that you can display different parts of your data if you want. Each of these are explained in more detail below.

- -

CSS

-

Sheetsee.js comes with a bare minimum stylesheet. This way you can customize your site to look the way you want to it or to match an existing site's design.

- -

Client-side or Server-side

-

Sheetsee.js comes in two flavors, client-side (this repo) and server-side (sheetsee-cache). The client-side is the most approachable and straightforward, you just include sheetsee.js and the dependencies on your page and use sheetsee.js as normal.

-

The server-side version is built with Node.js and you'll need to understand Node and be publishing to a server that runs Node.js apps. This version saves the data on the server so that the browser doesn't have to fetch from Google at every request, which can sometimes be slow. You can set when the cache expires. It also allows for offline development, huzzah!

- -
-

The Short & Sweet

-
    -
  1. Link to Sheetsee.js and dependencies in your HTML header.
  2. -
  3. Create a place holder <div> in your HTML for any chart, map or table you want to have.
  4. -
  5. Create templates for tables in <script> tags.
  6. -
  7. Create a script tag that waits for the document to load and then executes any of the map, chart or tables you've specified in it.
  8. -
  9. Set it and forget. Now all you need to do is edit the spreadsheet and visitors will get the latest information everytime they load the page.
  10. -
-
- -

Bare Minimum Setup

-

Ignoring some HTML things to conserve space, you get the point. This gives you a page with a map of your spreadsheets points.

-
<html>
-    <head>
-        <script type="text/javascript" src="http://api.tiles.mapbox.com/mapbox.js/v1.0.0/mapbox.js"></script>
-        <script type="text/javascript" src="js/ICanHaz.js"></script>
-        <script type="text/javascript" src="js/jquery.js"></script>
-        <script type="text/javascript" src="js/tabletop.js"></script>
-        <script type="text/javascript" src="js/d3.js"></script>
-        <script type="text/javascript" src="js/sheetsee.js"></script>
-        <link href='http://api.tiles.mapbox.com/mapbox.js/v1.0.0/mapbox.css' rel='stylesheet' />
-    </head>
-    <style> #map {height: 600px; width: 600px;} </style>
-    <body>
-    <div id="map"></div>
-    <script type="text/javascript">
-      document.addEventListener('DOMContentLoaded', function() {
-        var gData
-        var URL = "0AvFUWxii39gXdFhqZzdTeU5DTWtOdENkQ1Y5bHdqT0E"
-        Tabletop.init( { key: URL, callback: showInfo, simpleSheet: true } )
-      })
-      function showInfo(data) {
-        gData = data
-        optionsJSON = ["something", "something"]
-        var geoJSON = Sheetsee.createGeoJSON(gData, optionsJSON)
-        var map = Sheetsee.loadMap("map")
-        Sheetsee.addTileLayer(map, 'examples.map-20v6611k')
-        var markerLayer = Sheetsee.addMarkerLayer(geoJSON, map, 11)
-        // customize the popup content
-        addPopups(map, markerLayer)
-        function addPopups(map, markerLayer) {
-          markerLayer.on('click', function(e) {
-            var feature = e.layer.feature
-            var popupContent = '<h3>' + feature.opts.something + '</h3>'
-            e.layer.bindPopup(popupContent,{closeButton: false})
-          })
-        }
-      }
-    </script>
-    </body>
-</html>
- -

Awesome Possibilities

-
    -
  1. Small newsrooms with data for stories but small dev teams.
  2. -
  3. Friends or groups collaborating on data for a website/project.
  4. -
  5. Using iftt.com to auto populate spreadsheets which are hooked to a website with Sheetsee.js.
  6. -
- -

Examples

-
    -
  1. Hack Spots
  2. -
  3. James Sconfitto make a map of his relationship with his wife <3
  4. -
- -

Getting Started

-

This bit is the same for both client-side and server-side versions.

-

Your Data

-

sheetsee

-

Your Google Spreadsheet should be set up with row one as your column headers. Row two and beyond should be your data. Each header and row becomes an oject in the final array that Tabletop.js delivers of your data.

-

sheetsee

-

There shouldn't be any breaks or horizontal organization in the spreadsheet. But, feel free to format the style of your spreadsheet as you wish; borders, fonts and colors and such do not transfer or affect your data exporting.

-
[{"name":"Coco","breed":"Teacup Maltese","kind":"Dog","cuddlability":"5","lat":"37.74832","long":"-122.402158","picurl":"http://distilleryimage8.s3.amazonaws.com/98580826813011e2bbe622000a9f1270_7.jpg","hexcolor":"#ECECEC","rowNumber":1}...]
- -

Hexcolor

-

sheetsee

-

You must add a column to your spreadsheet with the heading hexcolor (case insensitive). The maps, charts and such use colors and this is the easiest way to standardize that. The color scheme is up to you, all you need to do is fill the column with hexidecimal color values. This color picker by Devin Hunt is really nice. #Funtip: Coloring the background of the cell it's hexcolor brings delight!

- -

Geocoding

-

If you intend to map your data and only have addresses you'll need to geocode the addresses into lat/long coordinates. Mapbox built a plugin - that does this for you in Google Docs. You can also use websites like latlong.net to get the coordinates and paste them into rows with column headers lat and long.

- sheetsee -

Publishing Your Spreadsheet

-

sheetsee

-

You need to do this in order to generate a unique key for your spreadsheet, which Tabletop.js will use to get your spreadsheet data. In your Google Spreadsheet, click File > Publish to the Web. Then in the next window click Start Publishing; it will then turn into a Stop Publishing button.

-

sheetsee

-

You should have an address in a box at the bottom, your key is the portion between the = and the &. You'll retrieve this later when you hook up your site to the spreadsheet.

-

Your Website

-

Before you get started with Sheetsee.js you should plan out your website. Design it, create the basic markup and stylesheet.

-

For now, create empty div placeholders for the map, chart and tables you plan on including.

-

Hooking Up Your Data

-

Here the paths diverge:

-

Client-side Hookup

-

For client-siders, all you need to do is include the depences and sheetsee in your HTML <head> and then in a script tag at the bottom of your page, right before the </body> tag, you'll include this:

-
<script type="text/javascript">
-    document.addEventListener('DOMContentLoaded', function() {
-        var gData
-        var URL = "0AvFUWxii39gXdFhqZzdTeU5DTWtOdENkQ1Y5bHdqT0E"
-        Tabletop.init( { key: URL, callback: showInfo, simpleSheet: true } )
-    })
-    function showInfo(data) {
-        gData = data
-        //
-        //everything you do with sheetsee goes here
-        //
-    }
-</script>
-

The URL variable is the key from your spreadsheet's longer URL, explained above. Tabletop.init() takes that URL and execute's Tabletop, when it's done generating the table it executes the callback showInfo function. It's inside of this function that you'll then use your spreadsheet data, gData, to do all the Sheetsee.js goodness with.

-

Server-side Hookup

-

The server-side version is in the repo sheetsee-cache. It uses Node.js to go to Google, get the spreadsheet data (with a Node.js version of Tabletop.js, thanks Max Ogden!) and save it on the server. This means every user that visits the page doesn't have to wait on Google's response to load the charts from the data.

-

When the server builds your page, it will build in your data as the variable gData. All you need to do is add your scripts to the bottom of the page. For the tables/templating you'll need to wrap them in an event listener so that it doesn't try and build them before the data has settled.

-
<script type="text/javascript">
-    document.addEventListener('DOMContentLoaded', function() {
-        // table/templating things the rest can be in their own script tags if you'd like
-    })
-</script>
-

Running Locally

-

You can run this locally and it will check your internet connection - if you're not online it will use the last saved data allowing you to develop offline, yay!

-

Once you clone the repo, navigate there in Terminal, install the node modules and launch the server.

-
cd sheetsee-cache
-npm install
-node server.js
-

This will launch a local server you can visit and develop locally with in your browser.

-

Working With Your Data

-

Tabletop.js will return all of your data and it will be passed into your site as an array of objects called gData. Sheetsee.js has functions built in to help you filter or use that data in other ways if you'd like.

-

Play Along!

-

This page is using sheetsee. If you (are in Chrome and) right click on the page and select Inspect Element it will bring up the Web Inspector. Select the Console tab. Now you can interact with the data and functions from Sheetsee. Give the functions below a try - gData is the variable with the data (from this spreadsheet). - sheetsee -

Sheetsee.getKeyword(data, keyword)

-

This takes in your data, an array of objects, and searches for a string, keyword, in each piece of your data (formerly the cells of your spreadsheet). It returns an array of each row that contained a keyword match. Similarly, using `getKeywordCount(data, keyword)` will return just the number of times the keyword occured.

-
getKeyword(gData, "cat")
-// returns [{breed: "Fat", kind: "cat", hexcolor: "#CDCF83"...}, {breed: "Grey", kind: "cat", hexcolor: "#9C9B9A"...}, {breed: "Creepy", kind: "cat", hexcolor: "#918376"...}]
-

Sheetsee.getColumnTotal(data, column)

-

Given your data, an array of objects and a string column header, this functions sums each cell in that column, so they best be numbers.

-
getColumnTotal(gData, "cuddlability")
-// returns 11
-

Sheetsee.getAveragefromColumn(data, column)

-

A really simple function that builds on getColumnTotal() by returning the average number in a column of numbers.

-
getColumnAverage(gData, "cuddlability")
-// returns 1.8333333333333333
-

Sheetsee.getMin(data, column)

-

This will return an array of object or objects (if there is a tie) of the element with the lowest number value in the column you specify from your data.

-
getMin(gData, "cuddlability")
-// returns [{breed: "Fat", cuddlability: "0", hexcolor: "#CDCF83"...}, {breed: "Grey", cuddlability: "0", hexcolor: "#9C9B9A"...}, {breed: "Creepy", cuddlability: "0", hexcolor: "#918376"...}]
- -

Sheetsee.getMax(data, column)

-

This will return an array of object or objects (if there is a tie) of the element with the highest number value in the column you specify from your data.

-
getMax(gData, "cuddlability")
-// returns {breed: "Teacup Maltese", cuddlability: "5", hexcolor: "#ECECEC", kind: "Dog", lat: "37.74832", long: "-122.402158", name: "Coco"...}
- -
- - -

Don't Forget JavaScript Math

-

Create variables that are the sums, differences, multiples and so forth of others. Lots of info on that here on MDN.

-
var profit09 = Sheetsee.getColumnTotal(gData, "2009")
-var profit10 = Sheetsee.getColumnTotal(gData, "2010")
-var difference = profit09 - profit10
-

What These Little Bits are Good For

-

You don't have to just create tables of your data. You can have other portions of your page that show things like, "The difference taco consumption between last week and this week is..." These are easy to create with javascirpt math functions and knowing a little bit more about icanhas.js. View source on this page to see how I created "Most Cuddlable".

- -

Sheetsee.getMatches(data, filter, category)

-

Takes data as an array of objects, a string you'd like to filter and a string of the category you want it to look in (a column header from your spreadsheet).

-
getMatches(gData, "dog", "kind")
-

Returns an array of objects matching the category's filter.

-
[{"name": "coco", "kind": "dog"...}, {"name": "wolfgang", "kind": "dog"...},{"name": "cooc", "kind": "dog"...} ]
- -

Sheetsee.getOccurance(data, category)

-

Takes data as an array of objects and a string for category (a column header from your spreadsheet) you want tally how often an element occured.

-
getOccurance(gData, "kind")
-

Returns an object with keys and values for each variation of the category and its occurance.

-
{"dog": 3, "cat": 3}
- -

Sheetsee.makeColorArrayOfObject(data, colors)

-

If you use getOccurance() and want to then chart that data with d3.js, you'll need to make it into an array (instead of an object) and add colors back in (since the hexcolor column applies to the datapoints in your original dataset and not this new dataset).

-

This function takes in your data, as an object, an array of hexidecimal color strings which you define and the category you used in getOccurance().

-
var kinds = getOccurance(gData, "kind")
-var kindColors = ["#ff00ff", "#DCF13C"]
-var kindData = makeColorArrayOfObjects(mostPopBreeds, kindColors, "kind")
-

It will return an array of objects with units as the title of the occurance amount like so:

-
[{"kind": "dog", "units": 2, "hexcolor": "#ff00ff"}, {"kind": "cat", "units": 3, "hexcolor": "#DCF13C"}]
-

If you pass in an array of just one color it will repeat that color for all items. If you pass fewer colors than data elements it will repeat the sequences of colors for the remainder elements.

- -

Make a Map

-
-

Sheetsee.js uses Mapbox.js, a Leaflet.js plugin, to make maps.

-

Create an empty <div> in your HTML, with an id.

-
<div id="map"></div>
-

Next you'll need to create geoJSON out of your data so that it can be mapped.

- -

Sheetsee.createGeoJSON(data, optionsJSON)

-

This takes in your data and the parts of your data, optionsJSON, that you plan in your map's popups. If you're not going to have popups on your markers, don't worry about it then and just pass in your data.

-
var optionsJSON = ["name", "breed", "cuddlability"]
-var geoJSON = Sheetsee.createGeoJSON(gData, optionsJSON)
-

It will return an array in the special geoJSON format that map making things love.

-
[{
-  "geometry": {"type": "Point", "coordinates": [long, lat]},
-  "properties": {
-    "marker-size": "small",
-    "marker-color": lineItem.hexcolor
-  },
-  "opts": {the options you pass in},
-}}
- -

Sheetsee.loadMap(mapDiv)

-

To create a simple map, with no data, you simply call `.loadMap() and pass in a string of the mapDiv (with no #) from your HTML.

-
var map = Sheetsee.loadMap("map")
- -

Sheetsee.addTileLayer(map, tileLayer)

-

To add a tile layer, aka a custom map scheme/design/background, you'll use this function which takes in your map and the source of the tileLayer. This source can be a Mapbox id, a URL to a TileJSON or your own generated TileJSON. See Mapbox's Documentation for more information.

-
Sheetsee.addTileLayer(map, 'examples.map-20v6611k')
-

You can add tiles from awesome mapmakers like Stamen or create your own in Mapbox's Tilemill or online.

- -

Sheetsee.addMarkerLayer(geoJSON, map, zoomLevel)

-

To add makers to your map, use this function and pass in your geoJSON so that it can get the coordinates, your map so that it places the markers there and a zoom level.

-
var markerLayer = Sheetsee.addMarkerLayer(geoJSON, map, 11)
- -

Sheetsee.addPopups(map, markerLayer)

-

To customize the marker popup content in your map use this function and pass in your map and markerLayer.

-
 Sheetsee.addPopups(map, markerLayer)
-

To customize the marker popup content in your map you'll need to use this entire function on your website.

-
function addPopups(map, markerLayer) {
-  markerLayer.on('click', function(e) {
-    var feature = e.layer.feature
-    var popupContent = '<h2>' + feature.opts.name + '</h2>' +
-                        '<h3>' + feature.opts.breed + '</h3>'
-    e.layer.bindPopup(popupContent,{closeButton: false,})
-  })
-}
-

You will edit the popupContent variable however you'd like your popups to look. To reference the data you sent to you geoJSON you'll use feature.opts and then one of the column headers you passed into createGeoJSON().

- -

Make a Table

- -
-

Example - Local Pet Friends

- - Clear - no matches -
-
- - -

Sheetsee.js supports making multiple tables or templates with IcanHas.js. The tables can have multiple inputs for searches and table headers can be used to sort the data in that column. For each of these you'll need a <div> in your html, a <script> template and a <script> that calls table functions.

-

Your HTML Placeholder <div>

-

This is as simple as an empty <div> with an id. This id should match the script tempate id in the next section.

-
 <div id="siteTable"></div>
-

Your <script> Template

-

Your template is the mockup of what you'd like your table to look like and what content it should show. Most of this is up to you but if you want users to be able to click on headers and sort that column you must make a table row with table headers with the class tHeader.

-

The variables inside the {{}} must match the column headers in your spreadsheet. Lowercase (?) and remember spaces are ommited, so "Place Name" will become "placename".

-
<script id="siteTable" type="text/html">
-    <table>
-    <tr><th class="tHeader">City</th><th class="tHeader">Place Name</th><th class="tHeader">Year</th><th class="tHeader">Image</th></tr>
-      {{#rows}}
-        <tr><td>{{city}}</td><td>{{placename}}</td><td>{{year}}</td><td>{{image}}</td></tr>
-      {{/rows}}
-  </table>
-</script>
-

Your <script> Execution

-
<script type="text/javascript">
-    document.addEventListener('DOMContentLoaded', function() {
-        Sheetsee.makeTable(gData, "#siteTable")
-        Sheetsee.initiateTableFilter(gData, "#tableFilter", "#siteTable")
-    })
-</script>
-

To create another table, simply repeat the steps with the corresponding data and divs.

-
<div id="secondTable"></div>
-<script id="secondTable"> // your table template here </script>
-<script>
-  Sheetsee.makeTable(otherData, "#secondTable")
-  Sheetsee.initiateTableFilter(otherData, "#secondFilter", "#secondTable")
-</script>
-
-

Learn more about the things you can do with mustache.js.

- -

Sheetsee.makeTable(data, targetDiv)

-

You'll call this to make a table out of a data and tell it what targetDiv in the html to render it in (this should also be the same id as your script template id).

-
Sheetsee.makeTable(gData, "#siteTable")
- -

Table Filter/Search

-

If you want to have an input to allow users to search/filter the data in the table, you'll add this to your html:

-
<input id="tableFilter" type="text" placeholder="filter by.."></input>
-<span class="clear button">Clear</span>
-<span class="noMatches">no matches</span>
- -

Sheetsee.initiateTableFilter(data, filterDiv, tableDiv)

-

You will then call this function to make that input live:

-
Sheetsee.initiateTableFilter(gData, "#TableFilter", "#siteTable")
- -

Make a Chart

-

Sheetsee.js comes with a d3.js bar, pie and line chart. Each requires your data be an array of objects, formatted to contain "label" and "units" keys. See the section above on Your Data to learn about formatting.

-

You'll have to experiement with the charts to find the correct size your <div> will need to be to hold the chart with your data in it nicely.

-

You can also make your own d3 chart in a separate .js file, link to that and pass your data on to it. I'd love to see people building some other charts that will work with Sheetsee.

- -

Bar Chart

- -
-
-
- -

To create a bar chart you'll need to add a placeholder <div> in your HTML with an id.

-
<div id="barChart"></div>
-

In your CSS, give it dimensions.

-
#barChart {height: 400px; max-width: 600px; background: #F8CDCD;}
-

In a <script> tag set up your options.

-
var barOptions = {labels: "name", units: "cuddleability", m: [60, 60, 30, 150], w: 600, h: 400, div: "#barChart", xaxis: "no. of pennies", hiColor: "#FF317D"}
- -

Then call the d3BarChart() function with your data and options.

-
Sheetsee.d3BarChart(data, barOptions)
- -

Line Chart

- -
-
-
- -

To create a line chart you'll need to add a placeholder <div> in your html with an id.

-
<div id="lineChart"></div>
-

In your CSS, give it dimensions.

-
#lineChart {height: 400px; max-width: 600px; background: #F8CDCD;}
-

In a <script> tag set up your options.

-
var lineOptions = {labels: "name", units: "cuddleability", m: [80, 100, 120, 100], w: 600, h: 400, div: "#lineChart", yaxis: "no. of pennies", hiColor: "#14ECC8"}
- -

Then call the d3LineChart() function with your data and options.

-
Sheetsee.d3LineChart(data, lineOptions)
- -

Pie Chart

- -
-
-
- -

To create a bar chart you'll need to add a placeholder <div> in your html with an id.

-
<div id="pieChart"></div>
-

In your CSS, give it dimensions.

-
#pieChart {height: 400px; max-width: 600px; background: #F8CDCD;}
-

In a <script> tag set up your options. You must include labels and units, this tells it what you're charting. Because for the pie chart we're using data we got from getOccurance() and makeColorArrayofObject(), our units are already called units. If we were using original data, we might have units as "cuddleability" or something else.

-
var pieOptions = {labels: "kind", units: "units", m: [80, 80, 80, 80], w: 600, h: 400, div: "#pieChart", hiColor: "#14ECC8"}
- -

Then call the d3PieChart() function with your data and options.

-
Sheetsee.d3PieChart(data, pieOptions)
- -

Don't forget, right click this page, select View Source and scroll to the bottom and see exactly how these charts were set up!

- - -

Big Time Thanks

-

Thanks to Code for America for providing the platform me to build the first version of sheetsee.js for Macon, Georga.

-

Thanks to Dan Sinker at Open News for having faith and getting things together to make this Code Sprint happen and thanks to Matt Green at WBEZ for being a willing partner.

-

Thanks to Max Ogden for emotional support, teaching me JavaScript and working on the harder parts of Sheetsee.js - especially for making Tabletop.js for Node.js.

-

Thanks to all the authors and contributors to Tabletop.js, Mapbox.js, Leaflet.js, jQuery, ICanHas.js and d3.js. Thanks to Google and the Internet for existing and to all those who've written tutorials or asked or answered a question on StackOverflow.

-

Thanks to Mom and Dad for getting a computer in 1996 and the mIRC scripts I started writing that I suppose would eventually lead me here.

- -

Licensed under BSD. East Bay represent!

- - - - - - - - - diff --git a/index.html b/index.html deleted file mode 100644 index 27151c7a..00000000 --- a/index.html +++ /dev/null @@ -1,39 +0,0 @@ - - - Yo, yo, yo! - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/js/ICanHaz.js b/js/ICanHaz.js deleted file mode 100644 index 25a14ac6..00000000 --- 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 - - - - - - - - - -
- - - -``` - -## Awesome Possibilities - -1. Small newsrooms with data for stories but small dev teams. -2. Friends or groups collaborating on data for a website/project. -3. Using [iftt.com](http://www.ifttt.com) to auto populate spreadsheets which are hooked to a website with Sheetsee.js. - -## Examples -1. [Hack Spots](http://jlord.github.io/hack-spots) -2. [James Sconfitto](https://twitter.com/jugglingnutcase) make a [map of his relationship](https://github.com/jugglingnutcase/katiejamie) with his wife <3 - -## Getting Started - -This bit is the same for both client-side and server-side versions. - -### Your Data - -![sheetsee](https://raw.github.com/jllord/sheetsee-cache/master/img/spreadsheettodata.png) - -Your Google Spreadsheet should be set up with row one as your column headers. Row two and beyond should be your data. Each header and row becomes an oject in the final array that Tabletop.js delivers of your data. - -![sheetsee](https://raw.github.com/jllord/sheetsee-cache/master/img/nonos.png) - -There shouldn't be any breaks or horizontal organization in the spreadsheet. But, feel free to format the style of your spreadsheet as you wish; borders, fonts and colors and such do not transfer or affect your data exporting. - - [{"name":"Coco","breed":"Teacup Maltese","kind":"Dog","cuddlability":"5","lat":"37.74832","long":"-122.402158","picurl":"http://distilleryimage8.s3.amazonaws.com/98580826813011e2bbe622000a9f1270_7.jpg","hexcolor":"#ECECEC","rowNumber":1}...] - -#### Hexcolor - -![sheetsee](https://raw.github.com/jllord/sheetsee-cache/master/img/hexcolors.png) - -You must add a column to your spreadsheet with the heading _hexcolor_ (case insensitive). The maps, charts and such use colors and this is the easiest way to standardize that. The color scheme is up to you, all you need to do is fill the column with hexidecimal color values. This [color picker](http://color.hailpixel.com/) by [Devin Hunt](https://twitter.com/hailpixel) is really nice. #Funtip: Coloring the background of the cell it's hexcolor brings delight! - -#### Geocoding - -If you intend to map your data and only have addresses you'll need to geocode the addresses into lat/long coordinates. Mapbox built a [plugin](http://mapbox.com/tilemill/docs/guides/google-docs/#geocoding) - that does this for you in Google Docs. You can also use websites like [latlong.net](http://www.latlong.net/) to get the coordinates and paste them into rows with column headers _lat_ and _long_. - -> image of lat and long column headers - -#### Publishing Your Spreadsheet - -![sheetsee](https://raw.github.com/jllord/sheetsee-cache/master/img/publish.png) - -You need to do this in order to generate a unique key for your spreadsheet, which Tabletop.js will use to get your spreadsheet data. In your Google Spreadsheet, click _File_ > _Publish to the Web_. Then in the next window click _Start Publishing_; it will then turn into a _Stop Publishing_ button. - -![sheetsee](https://raw.github.com/jllord/sheetsee-cache/master/img/key.png) - -You should have an address in a box at the bottom, your key is the portion between the = and the &. You'll retrieve this later when you hook up your site to the spreadsheet. - -### Your Website - -Before you get started with Sheetsee.js you should plan out your website. Design it, create the basic markup and stylesheet. - -For now, create empty `div` placeholders for the map, chart and tables you plan on including. - -## Hooking Up Your Data - -Here the paths diverge: - -### Client-side Hookup - -For client-siders, all you need to do is include the dependencies and sheetsee in your HTML `` and then in a script tag at the bottom of your page, right before the `` tag, you'll include this: - -``` html - -``` - -The **URL** variable is the key from your spreadsheet's longer URL, explained above. `Tabletop.init()` takes that URL and execute's Tabletop, when it's done generating the table it executes the callback `showInfo` function. It's inside of this function that you'll then use your spreadsheet data, **gData**, to do all the Sheetsee.js goodness with. - -### Server-side Hookup - -The server-side version is in the repo [sheetsee-cache](http://www.github.com/jllord/sheetsee-cache). It uses [Node.js](http://www.nodejs.org) to go to Google, get the spreadsheet data (with a Node.js version of [Tabletop.js](http://npmjs.org/tabletop), thanks Max Ogden!) and save it on the server. This means every user that visits the page doesn't have to wait on Google's response to load the charts from the data. - -When the server builds your page, it will build in your data as the variable gData. All you need to do is add your scripts to the bottom of the page. For the tables/templating you'll need to wrap them in an event listener so that it doesn't try and build them before the data has settled. - -``` html - -``` - -#### Running Locally - -You can run this locally and it will check your internet connection - if you're not online it will use the last saved data allowing you to develop offline, yay! - -Once you [clone the repo](http://www.github.com/jllord/sheetsee-cache), navigate there in Terminal, install the node modules and launch the server. - -``` sh -cd sheetsee-cache -npm install -node server.js -``` - -This will launch a local server you can visit and develop locally with in your browser. - -## Working With Your Data - -Tabletop.js will return all of your data and it will be passed into your site as an _array of objects_ called **gData**. Sheetsee.js has functions built in to help you filter or use that data in other ways if you'd like. - -### Sheetsee.getKeyword(data, keyword) - -This takes in your data, an _array of objects_, and searches for a _string_, **keyword**, in each piece of your **data** (formerly the cells of your spreadsheet). It returns an array of each element containing a **keyword** match. Similarly, using `getKeywordCount(data, "keyword)` will return the just the number of times the **keyword** occured. - -``` js -getKeyword(gData, "cat") -// returns [{breed: "Fat", kind: "cat", hexcolor: "#CDCF83"...}, {breed: "Grey", kind: "cat", hexcolor: "#9C9B9A"...}, {breed: "Creepy", kind: "cat", hexcolor: "#918376"...}] -``` - -### Sheetsee.getColumnTotal(data, column) - -Given your **data**, an _array of objects_ and a _string_ **column** header, this functions sums each cell in that column, so they best be numbers. - -``` js -getColumnTotal(gData, "cuddlability") -// returns 11 -``` - -### Sheetsee.getAveragefromColumn(data, column) - -A really simple function that builds on `getColumnTotal()` by returning the average number in a **column** of numbers. - -``` js -getColumnAverage(gData, "cuddlability") -// returns 1.8333333333333333 -``` - -### Sheetsee.getMin(data, column) - -This will return an _array_ of _object_ or _objects_ (if there is a tie) of the element with the lowest number value in the **column** you specify from your **data**. - -``` js -getMin(gData, "cuddlability") -// returns [{breed: "Fat", cuddlability: "0", hexcolor: "#CDCF83"...}, {breed: "Grey", cuddlability: "0", hexcolor: "#9C9B9A"...}, {breed: "Creepy", cuddlability: "0", hexcolor: "#918376"...}] -``` - -### Sheetsee.getMax(data, column) - -This will return an _array_ of _object_ or _objects_ (if there is a tie) of the element with the highest number value in the **column** you specify from your **data**. - -``` js -getMax(gData, "cuddlability") -// returns {breed: "Teacup Maltese", cuddlability: "5", hexcolor: "#ECECEC", kind: "Dog", lat: "37.74832", long: "-122.402158", name: "Coco"...} -``` - -### Don't Forget JavaScript Math - -Create variables that are the sums, differences, multiples and so forth of others. Lots of info on that [here on MDN](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Math). - -``` js -var profit09 = Sheetsee.getColumnTotal(gData, "2009") -var profit10 = Sheetsee.getColumnTotal(gData, "2010") -var difference = profit09 - profit10 -``` - -#### What These Little Bits are Good For - -You don't have to just create tables of your data. You can have other portions of your page that show things like, "The difference taco consumption between last week and this week is..." These are easy to create with javascirpt math functions and knowing a little bit more about [icanhas.js](http://icanhazjs.com/). View source on this page to see how I created "Most Cuddlable". - -### Sheetsee.getMatches(data, filter, category) - -Takes **data** as an _array of objects_, a _string_ you'd like to **filter** and a _string_ of the **category** you want it to look in (a column header from your spreadsheet). - -``` js -getMatches(gData, "dog", "kind") -``` - -Returns an _array of objects_ matching the category's filter. - -``` js -[{"name": "coco", "kind": "dog"...}, {"name": "wolfgang", "kind": "dog"...},{"name": "cooc", "kind": "dog"...} ] -``` +![sheetseeimg](https://raw.github.com/jlord/sheetsee-cache/master/img/sheetsee-03.png) +# Sheetsee.js -### Sheetsee.getOccurance(data, category) - -Takes **data** as an _array of objects_ and a _string_ for **category** (a column header from your spreadsheet) you want tally how often an element occured. - -``` js -getOccurance(gData, "kind") -``` - -Returns an object with keys and values for each variation of the category and its occurance. - -``` js -{"dog": 3, "cat": 3} -``` - -### Sheetsee.makeColorArrayOfObject(data, colors) - -If you use `getOccurance()` and want to then chart that data with d3.js, you'll need to make it into an _array_ (instead of an object) and add colors back in (since the hexcolor column applies to the datapoints in your original dataset and not this new dataset). - -This function takes in your data, as an _object_, and an _array_ of hexidecimal color strings which you define. - -``` js -var kinds = getOccurance(gData, "kind") -var kindColors = ["#ff00ff", "#DCF13C"] - -var kindData = makeColorArrayOfObjects(mostPopBreeds, kindColors) -``` - -It will return an array of objects formatted to go directly into a d3 chart with the appropriate _units_ and _label keys_, like so: - -``` js -[{"label": "dog", "units": 2, "hexcolor": "#ff00ff"}, {"label": "cat", "units": 3, "hexcolor": "#DCF13C"}] -``` - -If you pass in an array of just one color it will repeat that color for all items. If you pass fewer colors than data elements it will repeat the sequences of colors for the remainder elements. - -## Make a Map - -Sheetsee.js uses [Mapbox.js](http://mapbox.com/mapbox.js), a [Leaflet.js](http://leafletjs.com/) plugin, to make maps. - -Create an empty `
` in your HTML, with an id. - -``` html -
-``` - -Next you'll need to create geoJSON out of your data so that it can be mapped. - -### Sheetsee.createGeoJSON(data, optionsJSON) - -This takes in your **data** and the parts of your data, **optionsJSON**, that you plan in your map's popups. If you're not going to have popups on your markers, don't worry about it then and just pass in your data. - -``` js -var optionsJSON = ["name", "breed", "cuddlability"] -var geoJSON = Sheetsee.createGeoJSON(gData, optionsJSON) -``` - -It will return an _array_ in the special geoJSON format that map making things love. - -``` js -[{ - "geometry": {"type": "Point", "coordinates": [long, lat]}, - "properties": { - "marker-size": "small", - "marker-color": lineItem.hexcolor - }, - "opts": {the options you pass in}, -}} -``` - - -### Sheetsee.loadMap(mapDiv) - -To create a simple map, with no data, you simply call `.loadMap() and pass in a _string_ of the **mapDiv** (with no #) from your HTML. - -``` js -var map = Sheetsee.loadMap("map") -``` - -### Sheetsee.addTileLayer(map, tileLayer) - -To add a tile layer, aka a custom map scheme/design/background, you'll use this function which takes in your **map** and the source of the **tileLayer**. This source can be a Mapbox id, a URL to a TileJSON or your own generated TileJSON. See [Mapbox's Documentation](http://mapbox.com/mapbox.js/api/v1.0.2/#L.mapbox.tileLayer) for more information. - -``` js -Sheetsee.addTileLayer(map, 'examples.map-20v6611k') -``` - -You can add tiles from awesome mapmakers like [Stamen](examples.map-20v6611k) or create your own in Mapbox's [Tilemill](http://www.mapbox.com/tilemill) or [online](https://tiles.mapbox.com/newmap#3.00/0.00/0.00). - -### Sheetsee.addMarkerLayer(geoJSON, map, zoomLevel) - -To add makers to your map, use this function and pass in your **geoJSON** so that it can get the coordinates, your **map** so that it places the markers there and a **zoom level**. - -``` js -var markerLayer = Sheetsee.addMarkerLayer(geoJSON, map, 11) -``` - -### Sheetsee.addPopups(map, markerLayer) - -To customize the marker popup content in your map you'll need to use this entire function on your website. - -``` js -function addPopups(map, markerLayer) { - markerLayer.on('click', function(e) { - var feature = e.layer.feature - var popupContent = '

' + feature.opts.name + '

' + - '

' + feature.opts.breed + '

' - e.layer.bindPopup(popupContent,{closeButton: false,}) - }) -} -``` - -You will edit the **popupContent** variable however you'd like your popups to look. To reference the data you sent to you geoJSON you'll use `feature.opts` and then one of the column headers you passed into `createGeoJSON().` - -## Make a Table - -Sheetsee.js supports making multiple tables or templates with IcanHas.js. The tables can have multiple inputs for filtering and table headers can be used to sort the data in that column. For each of these you'll need a `
` in your html, a ` -``` - -#### Your ` -``` - -To create another table, simply repeat the steps. - -``` html -
- - -``` - - Learn more about the things you can do with [mustache.js](http://mustache.github.io/). - - -### Sheetsee.makeTable(data, targetDiv) - -You'll call this to make a table out of a **data** and tell it what **targetDiv** in the html to render it in (this should also be the same id as your script template id). - -``` js -Sheetsee.makeTable(gData, "#siteTable") -``` - -## Table Filter/Search - -If you want to have an input to allow users to search/filter the data in the table, you'll add this to your html: - -``` html - -Clear -no matches -``` - -### Sheetsee.initiateTableFilter(data, filterDiv, tableDiv) - -You will then call this function to make that input live: - -``` js -Sheetsee.initiateTableFilter(gData, "#TableFilter", "#siteTable") -``` - -## Make a Chart - -Sheetsee.js comes with a d3.js bar, pie and line chart. Each requires your data be an _array of objects_, formatted to contain "label" and "units" keys. See the section above on Your Data to learn about formatting. - -You'll have to experiement with the charts to find the correct size your `
` will need to be to hold the chart with your data in it nicely. - -You can also make your own d3 chart in a separate .js file, link to that and pass your data on to it. I'd love to see people building some other charts that will work with Sheetsee. - -### Bar Chart - -To create a bar chart you'll need to add a placeholder `
` in your HTML with an id. - -``` html -
-``` - -In your CSS, give it dimensions. - -``` css -#barChart {height: 400px; max-width: 600px; background: #F8CDCD;} -``` - -In a `