Skip to content

Instantly share code, notes, and snippets.

@jkutianski
Forked from mbostock/.block
Last active December 23, 2015 10:09
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save jkutianski/6619909 to your computer and use it in GitHub Desktop.
Scatterplot w/toggle label selectors
sepalLength sepalWidth petalLength petalWidth species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa
4.6 3.1 1.5 0.2 setosa
5.0 3.6 1.4 0.2 setosa
5.4 3.9 1.7 0.4 setosa
4.6 3.4 1.4 0.3 setosa
5.0 3.4 1.5 0.2 setosa
4.4 2.9 1.4 0.2 setosa
4.9 3.1 1.5 0.1 setosa
5.4 3.7 1.5 0.2 setosa
4.8 3.4 1.6 0.2 setosa
4.8 3.0 1.4 0.1 setosa
4.3 3.0 1.1 0.1 setosa
5.8 4.0 1.2 0.2 setosa
5.7 4.4 1.5 0.4 setosa
5.4 3.9 1.3 0.4 setosa
5.1 3.5 1.4 0.3 setosa
5.7 3.8 1.7 0.3 setosa
5.1 3.8 1.5 0.3 setosa
5.4 3.4 1.7 0.2 setosa
5.1 3.7 1.5 0.4 setosa
4.6 3.6 1.0 0.2 setosa
5.1 3.3 1.7 0.5 setosa
4.8 3.4 1.9 0.2 setosa
5.0 3.0 1.6 0.2 setosa
5.0 3.4 1.6 0.4 setosa
5.2 3.5 1.5 0.2 setosa
5.2 3.4 1.4 0.2 setosa
4.7 3.2 1.6 0.2 setosa
4.8 3.1 1.6 0.2 setosa
5.4 3.4 1.5 0.4 setosa
5.2 4.1 1.5 0.1 setosa
5.5 4.2 1.4 0.2 setosa
4.9 3.1 1.5 0.2 setosa
5.0 3.2 1.2 0.2 setosa
5.5 3.5 1.3 0.2 setosa
4.9 3.6 1.4 0.1 setosa
4.4 3.0 1.3 0.2 setosa
5.1 3.4 1.5 0.2 setosa
5.0 3.5 1.3 0.3 setosa
4.5 2.3 1.3 0.3 setosa
4.4 3.2 1.3 0.2 setosa
5.0 3.5 1.6 0.6 setosa
5.1 3.8 1.9 0.4 setosa
4.8 3.0 1.4 0.3 setosa
5.1 3.8 1.6 0.2 setosa
4.6 3.2 1.4 0.2 setosa
5.3 3.7 1.5 0.2 setosa
5.0 3.3 1.4 0.2 setosa
7.0 3.2 4.7 1.4 versicolor
6.4 3.2 4.5 1.5 versicolor
6.9 3.1 4.9 1.5 versicolor
5.5 2.3 4.0 1.3 versicolor
6.5 2.8 4.6 1.5 versicolor
5.7 2.8 4.5 1.3 versicolor
6.3 3.3 4.7 1.6 versicolor
4.9 2.4 3.3 1.0 versicolor
6.6 2.9 4.6 1.3 versicolor
5.2 2.7 3.9 1.4 versicolor
5.0 2.0 3.5 1.0 versicolor
5.9 3.0 4.2 1.5 versicolor
6.0 2.2 4.0 1.0 versicolor
6.1 2.9 4.7 1.4 versicolor
5.6 2.9 3.6 1.3 versicolor
6.7 3.1 4.4 1.4 versicolor
5.6 3.0 4.5 1.5 versicolor
5.8 2.7 4.1 1.0 versicolor
6.2 2.2 4.5 1.5 versicolor
5.6 2.5 3.9 1.1 versicolor
5.9 3.2 4.8 1.8 versicolor
6.1 2.8 4.0 1.3 versicolor
6.3 2.5 4.9 1.5 versicolor
6.1 2.8 4.7 1.2 versicolor
6.4 2.9 4.3 1.3 versicolor
6.6 3.0 4.4 1.4 versicolor
6.8 2.8 4.8 1.4 versicolor
6.7 3.0 5.0 1.7 versicolor
6.0 2.9 4.5 1.5 versicolor
5.7 2.6 3.5 1.0 versicolor
5.5 2.4 3.8 1.1 versicolor
5.5 2.4 3.7 1.0 versicolor
5.8 2.7 3.9 1.2 versicolor
6.0 2.7 5.1 1.6 versicolor
5.4 3.0 4.5 1.5 versicolor
6.0 3.4 4.5 1.6 versicolor
6.7 3.1 4.7 1.5 versicolor
6.3 2.3 4.4 1.3 versicolor
5.6 3.0 4.1 1.3 versicolor
5.5 2.5 4.0 1.3 versicolor
5.5 2.6 4.4 1.2 versicolor
6.1 3.0 4.6 1.4 versicolor
5.8 2.6 4.0 1.2 versicolor
5.0 2.3 3.3 1.0 versicolor
5.6 2.7 4.2 1.3 versicolor
5.7 3.0 4.2 1.2 versicolor
5.7 2.9 4.2 1.3 versicolor
6.2 2.9 4.3 1.3 versicolor
5.1 2.5 3.0 1.1 versicolor
5.7 2.8 4.1 1.3 versicolor
6.3 3.3 6.0 2.5 virginica
5.8 2.7 5.1 1.9 virginica
7.1 3.0 5.9 2.1 virginica
6.3 2.9 5.6 1.8 virginica
6.5 3.0 5.8 2.2 virginica
7.6 3.0 6.6 2.1 virginica
4.9 2.5 4.5 1.7 virginica
7.3 2.9 6.3 1.8 virginica
6.7 2.5 5.8 1.8 virginica
7.2 3.6 6.1 2.5 virginica
6.5 3.2 5.1 2.0 virginica
6.4 2.7 5.3 1.9 virginica
6.8 3.0 5.5 2.1 virginica
5.7 2.5 5.0 2.0 virginica
5.8 2.8 5.1 2.4 virginica
6.4 3.2 5.3 2.3 virginica
6.5 3.0 5.5 1.8 virginica
7.7 3.8 6.7 2.2 virginica
7.7 2.6 6.9 2.3 virginica
6.0 2.2 5.0 1.5 virginica
6.9 3.2 5.7 2.3 virginica
5.6 2.8 4.9 2.0 virginica
7.7 2.8 6.7 2.0 virginica
6.3 2.7 4.9 1.8 virginica
6.7 3.3 5.7 2.1 virginica
7.2 3.2 6.0 1.8 virginica
6.2 2.8 4.8 1.8 virginica
6.1 3.0 4.9 1.8 virginica
6.4 2.8 5.6 2.1 virginica
7.2 3.0 5.8 1.6 virginica
7.4 2.8 6.1 1.9 virginica
7.9 3.8 6.4 2.0 virginica
6.4 2.8 5.6 2.2 virginica
6.3 2.8 5.1 1.5 virginica
6.1 2.6 5.6 1.4 virginica
7.7 3.0 6.1 2.3 virginica
6.3 3.4 5.6 2.4 virginica
6.4 3.1 5.5 1.8 virginica
6.0 3.0 4.8 1.8 virginica
6.9 3.1 5.4 2.1 virginica
6.7 3.1 5.6 2.4 virginica
6.9 3.1 5.1 2.3 virginica
5.8 2.7 5.1 1.9 virginica
6.8 3.2 5.9 2.3 virginica
6.7 3.3 5.7 2.5 virginica
6.7 3.0 5.2 2.3 virginica
6.3 2.5 5.0 1.9 virginica
6.5 3.0 5.2 2.0 virginica
6.2 3.4 5.4 2.3 virginica
5.9 3.0 5.1 1.8 virginica
/**
* Add dataset support to elements
* No globals, no overriding prototype with non-standard methods,
* handles CamelCase properly, attempts to use standard
* Object.defineProperty() (and Function bind()) methods,
* falls back to native implementation when existing
* Inspired by http://code.eligrey.com/html5/dataset/
* (via https://github.com/adalgiso/html5-dataset/blob/master/html5-dataset.js )
* Depends on Function.bind and Object.defineProperty/Object.getOwnPropertyDescriptor (shims below)
* Licensed under the X11/MIT License
*/
// Inspired by https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind#Compatibility
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
'use strict';
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
FNOP = function () {},
fBound = function () {
return fToBind.apply(
this instanceof FNOP && oThis ? this : oThis,
aArgs.concat(Array.prototype.slice.call(arguments))
);
};
FNOP.prototype = this.prototype;
fBound.prototype = new FNOP();
return fBound;
};
}
/*
* Xccessors Standard: Cross-browser ECMAScript 5 accessors
* http://purl.eligrey.com/github/Xccessors
*
* 2010-06-21
*
* By Eli Grey, http://eligrey.com
*
* A shim that partially implements Object.defineProperty,
* Object.getOwnPropertyDescriptor, and Object.defineProperties in browsers that have
* legacy __(define|lookup)[GS]etter__ support.
*
* Licensed under the X11/MIT License
* See LICENSE.md
*/
// Removed a few JSLint options as Notepad++ JSLint validator complaining and
// made comply with JSLint; also moved 'use strict' inside function
/*jslint white: true, undef: true, plusplus: true,
bitwise: true, regexp: true, newcap: true, maxlen: 90 */
/*! @source http://purl.eligrey.com/github/Xccessors/blob/master/xccessors-standard.js*/
(function () {
'use strict';
var ObjectProto = Object.prototype,
defineGetter = ObjectProto.__defineGetter__,
defineSetter = ObjectProto.__defineSetter__,
lookupGetter = ObjectProto.__lookupGetter__,
lookupSetter = ObjectProto.__lookupSetter__,
hasOwnProp = ObjectProto.hasOwnProperty;
if (defineGetter && defineSetter && lookupGetter && lookupSetter) {
if (!Object.defineProperty) {
Object.defineProperty = function (obj, prop, descriptor) {
if (arguments.length < 3) { // all arguments required
throw new TypeError("Arguments not optional");
}
prop += ""; // convert prop to string
if (hasOwnProp.call(descriptor, "value")) {
if (!lookupGetter.call(obj, prop) && !lookupSetter.call(obj, prop)) {
// data property defined and no pre-existing accessors
obj[prop] = descriptor.value;
}
if ((hasOwnProp.call(descriptor, "get") ||
hasOwnProp.call(descriptor, "set")))
{
// descriptor has a value prop but accessor already exists
throw new TypeError("Cannot specify an accessor and a value");
}
}
// can't switch off these features in ECMAScript 3
// so throw a TypeError if any are false
if (!(descriptor.writable && descriptor.enumerable &&
descriptor.configurable))
{
throw new TypeError(
"This implementation of Object.defineProperty does not support" +
" false for configurable, enumerable, or writable."
);
}
if (descriptor.get) {
defineGetter.call(obj, prop, descriptor.get);
}
if (descriptor.set) {
defineSetter.call(obj, prop, descriptor.set);
}
return obj;
};
}
if (!Object.getOwnPropertyDescriptor) {
Object.getOwnPropertyDescriptor = function (obj, prop) {
if (arguments.length < 2) { // all arguments required
throw new TypeError("Arguments not optional.");
}
prop += ""; // convert prop to string
var descriptor = {
configurable: true,
enumerable : true,
writable : true
},
getter = lookupGetter.call(obj, prop),
setter = lookupSetter.call(obj, prop);
if (!hasOwnProp.call(obj, prop)) {
// property doesn't exist or is inherited
return descriptor;
}
if (!getter && !setter) { // not an accessor so return prop
descriptor.value = obj[prop];
return descriptor;
}
// there is an accessor, remove descriptor.writable;
// populate descriptor.get and descriptor.set (IE's behavior)
delete descriptor.writable;
descriptor.get = descriptor.set = undefined;
if (getter) {
descriptor.get = getter;
}
if (setter) {
descriptor.set = setter;
}
return descriptor;
};
}
if (!Object.defineProperties) {
Object.defineProperties = function (obj, props) {
var prop;
for (prop in props) {
if (hasOwnProp.call(props, prop)) {
Object.defineProperty(obj, prop, props[prop]);
}
}
};
}
}
}());
// Begin dataset code
if (!document.documentElement.dataset &&
// FF is empty while IE gives empty object
(!Object.getOwnPropertyDescriptor(Element.prototype, 'dataset') ||
!Object.getOwnPropertyDescriptor(Element.prototype, 'dataset').get)
) {
var propDescriptor = {
enumerable: true,
get: function () {
'use strict';
var i,
that = this,
HTML5_DOMStringMap,
attrVal, attrName, propName,
attribute,
attributes = this.attributes,
attsLength = attributes.length,
toUpperCase = function (n0) {
return n0.charAt(1).toUpperCase();
},
getter = function () {
return this;
},
setter = function (attrName, value) {
return (typeof value !== 'undefined') ?
this.setAttribute(attrName, value) :
this.removeAttribute(attrName);
};
try { // Simulate DOMStringMap w/accessor support
// Test setting accessor on normal object
({}).__defineGetter__('test', function () {});
HTML5_DOMStringMap = {};
}
catch (e1) { // Use a DOM object for IE8
HTML5_DOMStringMap = document.createElement('div');
}
for (i = 0; i < attsLength; i++) {
attribute = attributes[i];
// Fix: This test really should allow any XML Name without
// colons (and non-uppercase for XHTML)
if (attribute && attribute.name &&
(/^data-\w[\w\-]*$/).test(attribute.name)) {
attrVal = attribute.value;
attrName = attribute.name;
// Change to CamelCase
propName = attrName.substr(5).replace(/-./g, toUpperCase);
try {
Object.defineProperty(HTML5_DOMStringMap, propName, {
enumerable: this.enumerable,
get: getter.bind(attrVal || ''),
set: setter.bind(that, attrName)
});
}
catch (e2) { // if accessors are not working
HTML5_DOMStringMap[propName] = attrVal;
}
}
}
return HTML5_DOMStringMap;
}
};
try {
// FF enumerates over element's dataset, but not
// Element.prototype.dataset; IE9 iterates over both
Object.defineProperty(Element.prototype, 'dataset', propDescriptor);
} catch (e) {
propDescriptor.enumerable = false; // IE8 does not allow setting to true
Object.defineProperty(Element.prototype, 'dataset', propDescriptor);
}
}
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.dot {
stroke: #000;
}
.legend rect{
cursor: pointer;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="html5-dataset.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.tsv("data.tsv", function(error, data) {
data.forEach(function(d) {
d.sepalLength = +d.sepalLength;
d.sepalWidth = +d.sepalWidth;
});
x.domain(d3.extent(data, function(d) { return d.sepalWidth; })).nice();
y.domain(d3.extent(data, function(d) { return d.sepalLength; })).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Sepal Width (cm)");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Sepal Length (cm)")
var dot = svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.sepalWidth); })
.attr("cy", function(d) { return y(d.sepalLength); })
.style("fill", function(d) { return color(d.species); })
.attr("data-species", function (d) {
return d.species;
})
.style("opacity", 1);
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color)
.on("click", function (d) {
dot.filter(function () {
return this.dataset.species === d;
})
.transition().duration(750)
.style("opacity", function () {
console.log(this.style.opacity);
return (parseInt(this.style.opacity)) ? 0 : 1;
});
});
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment