Permalink
Browse files

code + data commit

  • Loading branch information...
1 parent c6b8e66 commit a92ea5babeb48cef3f17ac048fa4b5439d75136b @iros committed Jun 29, 2012
View
@@ -1,4 +1,34 @@
-client-side-data-talk
+Building Client-Side Data-driven applications - Talk Materials
=====================
-LondonJS School Trip Client-Side Data contents
+# Contents
+
+This repo contains:
+
+* code samples (/code)
+* data (/data)
+
+# How do I run this code?
+
+From the root of the repo run your favorite basic http server.
+I'm a fan of `python -m SimpleHTTPServer`.
+
+# Do I have to run this code?
+
+No. The following examples also have jsBins you can view:
+
+* [underscore-basics](http://jsbin.com/ofoyur/edit#javascript,html,live)
+* [mvc-backbone](http://jsbin.com/ugedon/edit#javascript,html,live)
+* [mvc-canjs](http://jsbin.com/ayarad/edit#javascript,html,live)
+* [taffy-db](http://jsbin.com/ehakot/edit#javascript,html,live)
+* [crossfilter-basic](http://jsbin.com/iyabok/4/edit#javascript,html,live)
+* [crossfilter-nan](http://jsbin.com/ojuqoq/edit#javascript,html,live)
+* [miso-dataset-basics](http://jsbin.com/anodul/edit#javascript,html,live)
+* [miso-dataset-custom-type](http://jsbin.com/udikel/edit#javascript,html,live)
+* web-workers - Doesn't have a jsBin.
+* [json-streams](http://jsbin.com/ijitam/edit#javascript,html,live)
+
+# I have questions
+
+Great. Ping me at @ireneros on twitter or irene at bocoup.com.
+I also idle in may places on irc: #bocoup, #misoproject.
@@ -0,0 +1,64 @@
+// fetch our json file... this time with d3 just for fun.
+d3.json("../../data/heroes.json", function(heroes) {
+
+ // before we pass heroes out to crossfilter, remove those that don't
+ // have an intelligence property.
+ heroes_with_intelligence = _.filter(heroes, function(hero) {
+ return (typeof hero.intelligence !== "undefined" &&
+ !_.isNaN(hero.intelligence));
+ });
+
+ // pass the data through the crossfilter
+ var heroes_cf = crossfilter(heroes_with_intelligence);
+
+ // === building dimensions
+ // build an intelligence dimension
+ var intelligence_dim = heroes_cf.dimension(function(hero) {
+ return hero.intelligence;
+ });
+
+ // ==== basic filtering
+ // find all records that are in the upper quadrant
+ var lower_quad_intelligence_filter = intelligence_dim.filter([0, 0.25]),
+ lower_quad_intelligence = lower_quad_intelligence_filter.top(Infinity);
+
+ console.log("# Heroes with intelligence in the lower quadrant",
+ lower_quad_intelligence.length);
+
+ // === grouping
+ // clear filter
+ intelligence_dim.filterAll();
+
+ // find our min and max
+ var records = intelligence_dim.top(Infinity),
+ max = records[0].intelligence, // 0.06
+ min = records[heroes_with_intelligence.length-1].intelligence, // 1.12
+ bin_width = (max - min) / 4,
+ // bin stops
+ bins = [min + bin_width, min + bin_width*2, min + bin_width*3, min + bin_width*4];
+
+
+ // bin results by the quadrant they are in
+ var intelligence_grouping = intelligence_dim.group(function(intelligence) {
+ if (intelligence < bins[0]) {
+ return bins[0];
+ } else if (intelligence < bins[1]) {
+ return bins[1];
+ } else if (intelligence < bins[2]) {
+ return bins[2];
+ } else if (intelligence <= bins[3]) {
+ return bins[3];
+ }
+ }),
+
+ // get all groups.
+ intelligence_groups = intelligence_grouping.all();
+
+ // The key will be the grouping function result, the value
+ // by default will be count. we can always return something else.
+ for (var i = 0; i < bins.length; i++) {
+ console.log(intelligence_groups[i].key,
+ intelligence_groups[i].value);
+ }
+
+});
@@ -0,0 +1,19 @@
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Crossfilter Basic</title>
+ <meta name="author" content="Irene Ros">
+ <!-- Date: 2012-06-29 -->
+</head>
+<body>
+ Open console
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
+ <script type="text/javascript" src="https://raw.github.com/square/crossfilter/master/crossfilter.js"></script>
+ <script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script>
+ <script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
+ <script type="text/javascript" src="crossfilter-basic.js"></script>
+ </body>
+</html>
+
+
+
@@ -0,0 +1,22 @@
+var data = crossfilter([
+ {date: "2011-11-14T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab"},
+ {date: "2011-11-14T16:20:19Z", quantity: 2, total: NaN, tip: 100, type: "tab"},
+ {date: "2011-11-14T16:28:54Z", quantity: 1, total: 300, tip: 200, type: "visa"},
+ {date: "2011-11-14T16:30:43Z", quantity: 2, total: 90, tip: 0, type: "tab"},
+ {date: "2011-11-14T16:48:46Z", quantity: 2, total: 90, tip: 0, type: "tab"}
+]);
+
+// make a dimension for the total variable
+var total_dimension = data.dimension(function(d) { return d.total; }),
+
+ // find al records that have 90 as the value
+ na_records = total_dimension.filter(90).top(Infinity),
+
+ // random output ul
+ elRecords = $('ul#records');
+
+// output resulting filter values.
+elRecords.empty();
+for (var i = 0; i < na_records.length; i++) {
+ $('<li>', { text : na_records[i].total}).appendTo(elRecords);
+}
@@ -0,0 +1,19 @@
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Crossfilter NaN Issue</title>
+ <meta name="author" content="Irene Ros">
+ <!-- Date: 2012-06-29 -->
+</head>
+<body>
+ <ul id="records">
+
+ </ul>​
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
+ <script type="text/javascript" src="https://raw.github.com/square/crossfilter/master/crossfilter.js"></script>
+ <script type="text/javascript" src="crossfilter-nan.js"></script>
+ </body>
+</html>
+
+
+
@@ -0,0 +1,20 @@
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>JSON Streams</title>
+ <meta name="author" content="Irene Ros">
+ <!-- Date: 2012-06-29 -->
+</head>
+<body>
+ <div id="heroes">
+ Open Console
+ </div>​
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
+ <script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
+ <script type="text/javascript" src="http://ireneros.com/LondonJS/browserify-bundle.js"></script>
+ <script type="text/javascript" src="json-streams.js"></script>
+ </body>
+</html>
+
+
+
@@ -0,0 +1,100 @@
+// Based on fantastic work by @maxogden:
+// http://substance.io/maxogden/replicating-large-datasets-into-html5
+// * This is faking the actual chunking - replace the url with a proper
+// chunked file. Look for transfer-encoding: chunked in your headers.
+// ==================================================================
+// to build your own version of the browser bundle:
+// from a command line
+// npm install browserify -g
+// browserify -r events -r buffer -r stream -r util -r JSONStream -o browserify-bundle.js
+// or download here: http://ireneros.com/LondonJS/browserify-bundle.js
+// ==================================================================
+
+// set up node library dependencies.
+var stream = require('stream'),
+ util = require('util'),
+ JSONStream = require('JSONStream');
+
+
+function XHRStream(xhr) {
+
+ var self = this;
+
+ // call stream constructor
+ stream.Stream.apply(this, arguments);
+
+ self.xhr = xhr;
+
+ // will be used to track where each request ends
+ // so that we can slice the right amount of data to pass to
+ // the parser.
+ self.offset = 0;
+
+ // bind to state change to hook into readyState 3
+ xhr.onreadystatechange = function() {
+ self.handleReadyStateChange();
+ }
+
+ xhr.send(null);
+}
+
+// inherit from stream.Stream.
+util.inherits(XHRStream, stream.Stream);
+
+// handle ready state change (catches 3.)
+XHRStream.prototype.handleReadyStateChange = function() {
+
+ // intercept ready state 3 and emit the data to the json
+ // stream parser.
+ if (this.xhr.readyState === 3) {
+ this.write();
+ }
+
+ // add an end state to catch the end of streaming.
+ if (this.xhr.readyState === 4) {
+ this.emit('end');
+ }
+};
+
+// On ready state change 3, pass the response text from this
+// request to the json parser (by emitting it.)
+XHRStream.prototype.write = function() {
+
+ // as long as we actually have new data
+ if (this.xhr.responseText.length > this.offset) {
+
+ // removes already processed data from previous state changes.
+ var data = this.xhr.responseText.slice(this.offset);
+
+ // emits the current data chunk
+ this.emit('data', data);
+
+ // resets the offset to include current text.
+ this.offset = this.xhr.responseText.length;
+ }
+};
+
+
+// Create a new XHR Request and fetch a large json file.
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "../../data/heroes.json", true);
+
+// create a new XHRStream object
+var xhrstream = new XHRStream(xhr);
+
+// create a new json stream parser that will look for all the elements
+// inside the root json element
+var json = JSONStream.parse([/./]);
+
+// setup json stream pipe from the xhr stream
+xhrstream.pipe(json);
+
+// on new incoming data, just output each hero's name
+json.on('data', function(hero) {
+ console.log(hero.name);
+});
+
+// on new incoming data, just output each hero's name
+json.on('done', function() {
+ console.log("Done");
+});
@@ -0,0 +1,19 @@
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Miso Dataset Custom Type</title>
+ <meta name="author" content="Irene Ros">
+ <!-- Date: 2012-06-29 -->
+</head>
+<body>
+ <h3>Top hair colors for all heroes and villains</h3>
+ <ul id="heroHairColor">
+ <li>Loading...</li>
+ </ul>
+
+ <!-- resources -->
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
+ <script type="text/javascript" src="http://cloud.github.com/downloads/misoproject/dataset/miso.ds.deps.min.0.2.0.js"></script>
+ <script type="text/javascript" src="miso-dataset-basics.js"></script>
+ </body>
+</html>
@@ -0,0 +1,31 @@
+// Instantiate a new Miso Dataset object and point it
+// at our trusty hero database.
+var heroes = new Miso.Dataset({
+   url: '../../data/heroes.json'
+});
+
+// fetch data
+heroes.fetch().then(function() {
+   
+ // === Products
+ console.log("intelligence",
+ "min", heroes.min("intelligence"),
+ "max", heroes.max("intelligence"));
+
+ // === derivatives + sorting
+ var heroes_by_haircolor = heroes.countBy("Hair_color")
+ .sort(function(row1, row2) {
+ if (row1.count > row2.count) { return -1; }
+ if (row1.count < row2.count) { return 1; }
+ return 0;
+ });
+
+ // ==== output colors
+ var list = $('ul#heroHairColor').empty();
+ for(var i = 0; i < 10; i++) {
+ var row = heroes_by_haircolor.rowByPosition(i);
+ $('<li>', {
+ text : row.Hair_color + "(" + row.count + ")"
+ }).appendTo(list);
+ }
+});
@@ -0,0 +1,16 @@
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Miso Dataset Custom Type</title>
+ <meta name="author" content="Irene Ros">
+ <!-- Date: 2012-06-29 -->
+</head>
+<body>
+ Open Console!
+
+ <!-- resources -->
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
+ <script type="text/javascript" src="http://cloud.github.com/downloads/misoproject/dataset/miso.ds.deps.min.0.2.0.js"></script>
+ <script type="text/javascript" src="miso-dataset-custom-type.js"></script>
+ </body>
+</html>
Oops, something went wrong.

0 comments on commit a92ea5b

Please sign in to comment.