Last active
November 10, 2015 06:11
-
-
Save chabb/cccc506b3118734d5eab to your computer and use it in GitHub Desktop.
SOME STUFF
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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