Skip to content

Instantly share code, notes, and snippets.

@chabb
Last active November 10, 2015 06:11
Show Gist options
  • Save chabb/cccc506b3118734d5eab to your computer and use it in GitHub Desktop.
Save chabb/cccc506b3118734d5eab to your computer and use it in GitHub Desktop.
SOME STUFF
<html>
<head>
<title>STUFF</title>
<meta charset="utf-8" />
<script src="http://d3js.org/d3.v3.min.js" type="text/JavaScript"></script>
</head>
<style>
.dominos {
stroke:black;
}
.axis text {
font: 10px sans-serif;
}
.axis line,
.axis path {
fill: none;
stroke: #000;
stroke-width: -2px;
shape-rendering: crispEdges;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px 8px 8px 0px;
pointer-events: none;
}
div.tooltip > span {
vertical-align: middle;
line-height: 28px;
}
</style>
<body>
<div id="content">
<button id="f_empty">Filter Empty Sets</button>
<button id="f_full">Display Empty Sets</button>
<button id="f_sortFull">Sort (Full)</button>
<button id="f_sortEmpty">Sort (Empty)</button>
</div>
</body>
</html>
<script>
var D;
d3.setsIntersections = function(maps) {
//http://stackoverflow.com/questions/26028124/the-intersection-of-all-combinations-of-n-sets
var list = [];
var dominoMapping = {};
var _i = 1;
var intersections = {};
var elements = 0;
var numberOfSets = maps.keys().length;
maps.forEach(function(k,v){
console.log(k,v.content.length);
dominoMapping[k] = _i++;
for(var i=0;i<v.content.length;i++)
list.push({set:k,element:v.content[i]});
})
console.log(list);
var limit = Math.pow(2,_i-1)
for (var t=0;t<limit;t++) {
intersections[t+''] = {
elements:[],
dominoRepresentation : computeDominoRepresentation(t)
};
}
var listA = d3.nest()
.key(function(d) { return d.element })
.map(list);
console.log(listA);
elements = list.length;
var keys = d3.keys(listA);
for (var i=0;i<keys.length;i++) {
var arrayOfSets = (listA[keys[i]]);
var setId = computeIntersectionID(arrayOfSets);
if (arrayOfSets.length == 1 ) {
intersections[setId+''].elements.push(keys[i]);
} else {
intersections[setId+''].elements.push(keys[i]);
}
}
console.log(intersections);
return {
intersections : intersections,
distinctElements : elements,
numberOfSets : numberOfSets,
dominoMapping : dominoMapping,
numberOfDominos : limit
}
function computeIntersectionID(array) {
var total = 0;
for (var i=0;i<array.length;i++) {
var mapping = dominoMapping[array[i].set];
total = total + Math.pow(2,mapping-1);
}
return total;
}
function computeDominoRepresentation(setsId) {
var domino = [];
//console.log('Trying to compute',setsId,numberOfSets);
for (var l=0;l<numberOfSets;l++) {
id = (1 << l);
var value = id & setsId;
var newValue = (value >> l);
console.log('testing',l+1,id,value,newValue);
domino.push(newValue);
}
return domino;
}
}
var contents = d3.map([
{ name : "mice", content:["a","b","c","d","q","ii"]},
{ name : "mdfice", content:["a","b","c","d","q","ii"]},
{ name : "ghouls", content:["rip","ba","pa","qd","ii","df","fds","dfs","dfs"]},
{ name : "cat", content:["gd","zd","sc","sq","ii"]},
{ name : "martian", content:["qc","qp","sc","eede","bz","grm","ii"]}
],function(d) {return d.name;});
var result = d3.setsIntersections(contents);
var keys = d3.keys(result.intersections);
var width = 960 // should add the y axis padding
height = 900 ;
var dominoHeight = 400;
var margin = {
left : 10,
right : 10,
top : 10,
bottom :10
}
//tooltip settings
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// should fine the biggest sets to determine the highest range
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], 0,0);
x.domain(d3.keys(result.intersections));
var yDomino = d3.scale.ordinal()
.rangeRoundBands([0, x.rangeBand()*contents.keys().length], .0,0);
yDomino.domain(d3.extent([d3.keys(result.interesections)]));
x.domain(d3.keys(result.intersections));
// mimick the ordinal scal with a linear scale ();
var xMimickOrdinal = d3.scale.linear()
.range([0,width])
var stuff = d3.extent(
d3.keys(result.intersections).map(function(d) { return parseInt(d)})
);
console.log(stuff);
xMimickOrdinal.domain
(
[stuff[0],stuff[1]]
)
var dw = x.rangeBand();
// recreate data
var data = [];
var filteredDatas = [];
// compute immediately non filtered;
var biggestNumberOfElementsInSet = 0;
for (var i=0;i<keys.length;i++) {
var elements = result.intersections[keys[i]].elements.length
var dataPoint = {value:elements
, id:keys[i],m:result.intersections[keys[i]].dominoRepresentation,w:dw,n:result.numberOfSets }
data.push(dataPoint)
if (dataPoint.value > 0) filteredDatas.push(dataPoint);
if (elements > biggestNumberOfElementsInSet) biggestNumberOfElementsInSet = elements ;
console.log('working',biggestNumberOfElementsInSet,elements);
}
var y = d3.scale.linear()
.range([height-dominoHeight,0])
.domain(d3.extent([0,biggestNumberOfElementsInSet]));
var xAxis = d3.svg.axis()
.scale(x)
.tickValues([])
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(biggestNumberOfElementsInSet, "-");
var yAxisDomino = d3.svg.axis()
.scale(yDomino)
.orient("left")
.ticks(10, "%");
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right+100) // grr the padding for x axis
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("class","main-group")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");;
var chart = svg.append("g").attr("transform","translate(100,0)");
var xAxisSelection = chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height-dominoHeight) + ")")
.call(xAxis);
var yAxisSelection = chart.append("g")
.attr("class", "y axis")
.call(yAxis)
chart.append("g")
.attr("class", "y domino axis")
.attr("transform","translate(" + (-10) + "," + (40+height-dominoHeight)+ ")")
.call(yAxisDomino);
// 1 domino top bottom
// 2 domino top bottom one intersections
// 3 domino top bottom two intersections
var myDomino = dominoGen()
.width(function(d,i) {console.log('index',i,d); return d.w; })
.numberOfDominos(function(d,i) { return d.n; });
console.log('prout');
var bars = chart.selectAll(".bar")
.data(data,function(d,i) { return d.id});
bars.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d,i) { console.log('SOME STUFF',d,i);return x(i)+5; })
.attr("width", x.rangeBand()-5)
.attr("y", function(d,i) { return y(d.value); })
.attr("height", function(d) { return(height-dominoHeight)-y(d.value); });
var barChart = {};
var dispatch = d3.dispatch(barChart, "hover");
bars.on("mouseover", function(d) {
var bb = this.getBoundingClientRect();
d3.select(this)
.transition()
.duration(200)
.ease('cubic-in-out')
.attr("fill","gray");
div.html('<span>'+d.value+'</span>')
div.transition()
.duration(500)
.style("opacity", .98)
.style("left", (bb.left) + "px")
.style("top", (bb.top-35)+window.scrollY+ "px");
dispatch.hover([d])
})
bars.on("mouseout", function(d) {
d3.select(this)
.transition()
.duration(200)
.ease('cubic-in-out')
.attr("fill","black");
div.transition()
.duration(500)
.style("opacity", 0);
dispatch.hover([])
});
d3.rebind(barChart, dispatch, "on");
barChart.on("hover", function(hovered) {
highlightDominos(hovered);
});
var enter = chart
.append("g")
.attr("class","domino-axis")
.attr("transform","translate("+0+","+(40+height-dominoHeight)+")")
.selectAll("g.dominos")
.data(data,function(d){return d.id})
.enter();
var center = (dw) / 2;
var r = center / 1.5
var dominosChart = {};
var dominos = enter.append("g")
.attr("class", "dominos")
.attr("transform", function(d,i){ return "translate("+(dw * i )+",0)" });
//var subsection = n-1;
// var heightPerSubSection = w;
// var h = heightPerSubSection * n;
dominos.append("rect")
.attr("fill","white")
.attr("stroke","none")
.attr("x",0)
.attr("y",0)
.attr("width",function(d,i){return d.w})
.attr("height",function(d,i){return d.w*d.n});
dominos.append("path")
.attr("class", "dominos")
.attr("d", myDomino);
// data of circe is an array representing lit circle, eg : [0,1,0,0,1]
dominos.selectAll("circle").data(function(d){return d.m})
.enter()
.append("circle")
.attr("cx",function(d,i){ return center})
.attr("cy",function(d,i){ return center + (dw)*i} )
.attr("r", function(d) { return r })
.attr("fill","orange")
.attr("visibility",function(d,i) {
return d ? "visible" : "hidden";
})
var dispatchDomino = d3.dispatch(dominosChart, "hover");
d3.rebind(dominosChart, dispatchDomino, "on");
dominosChart.on("hover", function(hovered) {
console.log('WORKING...');
});
/*svg.selectAll("path.dominos")
.data(data)
.enter().append("path")
.attr("class", "dominos")
.attr("d", myDomino)
*/
console.log('RESULT',result);
d3.select('#f_empty').on("click",function() {
filterEmptySets();
})
d3.select('#f_full').on("click",function() {
toggleFullSet();
})
d3.select('#f_sortFull').on("click",function() {
sortFullSet();
})
d3.select('#f_sortEmpty').on("click",function() {
sortEmptySet();
})
function zoomed(e) {
console.log('gni',y.domain(),xMimickOrdinal.domain());
//d3.select('.x.axis').call(xAxis);
// try to retake the domain
a = Math.floor(xMimickOrdinal[0]),b = Math.ceiling(xMimickOrdinal[1]);
domain = [];
for (a;a<b;a++) {
domain.push(""+a);
}
x.domain(domain);
d3.select('.y.axis').call(yAxis);
d3.select('.y.axis').call(yAxis);
//d3.select(this).scale(d3.event.scale);
// d3.select(this).attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
console.log('the scale',x,y);
/*var zoom = d3.behavior.zoom()
.y(y)
.x(xMimickOrdinal)
.on("zoom", zoomed);
svg.call(zoom);
*/
function highlightDominos(data) {
var rects = chart.selectAll("g.dominos");
var dh = rects.data(data,function(d) { return d.id});
dh.selectAll("rect").transition().duration(250).attr("fill","red")
dh.exit().selectAll("rect").transition().duration(250).attr("fill","white");
dh.selectAll('circle').transition().duration(750).attr("fill","green");
dh.exit().selectAll('circle').transition().duration(750).attr("fill","orange");
//.data(function(d){console.log('WUT',d);return d.m});
}
//TODO _______REFACTOR_____________
function filterEmptySets() {
console.log('filter');
var bars = chart.selectAll(".bar")
.data(filteredDatas,function(d,i) { return d.id})
bars.transition().duration(1000).attr("x",function(d,i) { return x(i)+5})
bars.exit()
.transition().duration(1000)
.attr("x", function(d,i) { return -1000 - (10 * i)}) // should multiply by width to have nice effects
var dominos = chart
.selectAll("g.dominos")
.data(filteredDatas,function(d,i) { return d.id})
dominos.exit()
.transition().duration(1000)
.attr("transform", function(d,i){ return "translate("+ (-1000-(dw*i))+",0)" });
dominos.transition().duration(1000)
.attr("transform", function(d,i){ return "translate("+(dw * i )+",0)" });
}
function sortEmptySet() {
console.log('filter');
var sorted = filteredDatas.sort(function(a,b) {return b.value-a.value;});
var bars = chart.selectAll(".bar")
.data(sorted,function(d,i) { return d.id})
bars.transition().duration(1000).attr("x",function(d,i) { return x(i)+5})
bars.exit()
.transition().duration(1000)
.attr("x", function(d,i) { return -1000 - (10 * i)}) // should multiply by width to have nice effects
var dominos = chart
.selectAll("g.dominos")
.data(sorted,function(d,i) { return d.id})
dominos.exit()
.transition().duration(1000)
.attr("transform", function(d,i){ return "translate("+ (-1000-(dw*i))+",0)" });
dominos.transition().duration(1000)
.attr("transform", function(d,i){ return "translate("+(dw * i )+",0)" });
}
function sortFullSet() {
var sorted = data.sort(function(a,b) {return a.value-b.value;});
var bars = chart.selectAll(".bar")
.data(sorted,function(d,i) { return d.id})
bars.transition().duration(1000).attr("x",function(d,i) { return x(i)+5})
bars.exit()
.transition().duration(1000)
.attr("x", function(d,i) { return -1000 - (10 * i)}) // should multiply by width to have nice effects
var dominos = chart
.selectAll("g.dominos")
.data(sorted,function(d,i) { return d.id})
dominos.exit()
.transition().duration(1000)
.attr("transform", function(d,i){ return "translate("+ (-1000-(dw*i))+",0)" });
dominos.transition().duration(1000)
.attr("transform", function(d,i){ return "translate("+(dw * i )+",0)" });
}
function toggleFullSet() {
var bars = chart.selectAll(".bar")
.data(data,function(d,i) { return d.id})
bars.transition().duration(1000).attr("x",function(d,i) { return x(i)+5})
bars.exit()
.transition().duration(1000)
.attr("x", function(d,i) { return -1000 - (10 * i)}) // should multiply by width to have nice effects
var dominos = chart
.selectAll("g.dominos")
.data(data,function(d,i) { return d.id})
dominos.exit()
.transition().duration(1000)
.attr("transform", function(d,i){ return "translate("+ (-1000-(dw*i))+",0)" });
dominos.transition().duration(1000)
.attr("transform", function(d,i){ return "translate("+(dw * i )+",0)" });
}
// ___________REFACTOR____________________
function dominoGen() {
//set defaults accessor
var numberOfDominos = function(d,i) {console.log('stuff',i); return d.numberOfSets; },
width = function(d,i) {console.log('index',i); return d.x; };
//returned function to generate circle path
function circle(d) {
console.log("CALLED WITH",d)
var w = d3.functor(width).call(this, d),
n = d3.functor(numberOfDominos).call(this, d);
console.log(w,h,n);
var subsection = n-1;
var heightPerSubSection = w;
var h = heightPerSubSection * n;
var path = "";
for (var i=0; i<=subsection+1;i++) {
path = path + "M 0 "+(heightPerSubSection*i)+" H "+w;
}
path = path + " M 0 0 V "+h;
path = path + " M "+w+" 0 V"+h;
return path+" z";
}
//getter-setter methods
circle.numberOfDominos = function(value) {
if (!arguments.length) return numberOfDominos; numberOfDominos = value; return circle;
};
circle.width = function(value) {
if (!arguments.length) return width; width = value; return circle;
};
return circle;
}
d3.svg.dominoGenerator = dominoGen;
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment