block by enjalot 5545957

1024 members scrolly

Full Screen

index.html


<div class=header>
</div>

<div class=fixie>
</div>

_.md

config.json

{"description":"1024 members scrolly","endpoint":"","display":"div","public":true,"require":[{"name":"crossfilter","url":"http://square.github.io/crossfilter/crossfilter.v1.min.js"}],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"meetups.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"rsvps.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"members.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"style.css":{"default":true,"vim":false,"emacs":false,"fontSize":12},"index.html":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"thumbnail":"http://i.imgur.com/rns10Nv.png"}

inlet.js

var baseAvatarUrl = "http://photos1.meetupstatic.com/photos/member"

var avatarWidth = 40;
var avatarHeight = 40;

var rectWidth = 20;
var rectHeight = 20;
var rectSpace = 10;

//////////////////////////////////////////////////////////////////////////////
// Data preparation
//////////////////////////////////////////////////////////////////////////////

//we create a lookup table for the members and meetup events
var membersDict = {};
var members = tributary.members;
members.sort(function(a,b) {
  return a.joined - b.joined
})
members.forEach(function(member) {
  membersDict[member.id] = member;
});
var firstMember = tributary.members[0];
var lastMember = tributary.members[tributary.members.length - 1];


var meetupsDict = {};
var meetups = tributary.meetups;
meetups.sort(function(a,b) {
  return a.time - b.time
})
meetups.forEach(function(meetup) {
  meetupsDict[meetup.id] = meetup;
});

var memberXf = crossfilter(members);
var memberDims = {
  "joined": memberXf.dimension(function(d) { return d.joined })
}

var dayGroup = memberDims.joined.group(function(d) { return d3.time.day.floor(new Date(d)) });
var membersByDay = dayGroup.all();

var dayBuckets = {}
members.forEach(function(member) {
  var day = d3.time.day.floor(new Date(member.joined))
  if(!dayBuckets[day]) {
    dayBuckets[day] = [member]
  } else {
    dayBuckets[day].push(member)
  }
})

var xf = crossfilter(tributary.rsvps);
var dims = {
  "member": xf.dimension(function(d) { return d.id }),
  "events": xf.dimension(function(d) { return d.evt }),
  "rsvp": xf.dimension(function(d) { return d.response })
};

dims.rsvp.filter('yes');

//////////////////////////////////////////////////////////////////////////////
// Rendering
//////////////////////////////////////////////////////////////////////////////
var display = d3.select("#display")


var width = tributary.sw;
var height = tributary.sh;
var timelineHeight = 100;


//////////////////////////////////////////////////////////////////////////////
// Scrolling
//////////////////////////////////////////////////////////////////////////////


//calculate our intended height
var visHeight = membersByDay.length * (rectHeight + rectSpace);

var timeScale = d3.time.scale()
  .domain([firstMember.joined, lastMember.joined])
  .range([0, visHeight])
  
var mbdExtent = d3.extent(membersByDay, function(d) { return d.value })
var mbdScale = d3.scale.linear()
.domain(mbdExtent)
.range([rectWidth,200])

var format = d3.time.format("%b %d, %Y")

////////////////////////////////////
//draw events
////////////////////////////////////
var meetupdiv = display.append("div").classed("meetups", true)

var descs = meetupdiv.selectAll("div.meetup")
.data(meetups)
.enter()
.append("div")
.classed("meetup", true)
.style({
  top: function(d,i) { return timeScale(d3.time.day.ceil(new Date(d.time))) + "px" },
  left: "0px",
  width: "800px",
  height: "20px"
})
.append("div")
.classed("meetup-desc", true)

descs.append("span").text(function(d) { return d.name }).classed("name", true)
descs.append("br")
descs.append("span").text(function(d) { return format(new Date(d.time)) })
descs.append("br")
descs.append("span").text(function(d) { return "@ " +d.venue })
descs.append("br")
descs.append("span")
.classed("rsvplink", true)
.text(function(d) { 
  var rsvpers = dims.events.filter(d.id);
  var nRsvpers = rsvpers.top(Infinity).length;

  return nRsvpers
})
.on("click", function(d,i) {
})



////////////////////////////////////
//draw faces
////////////////////////////////////
var bardiv = display.append("div")
.classed("facebar", true)
.style({
  height: 20 + visHeight + "px"
})

bardiv.selectAll(".face")
.data(members, function(d) { return d.id })
.enter()
.append("div")
.classed("face", true)
.style({
  top: function(d,i) { return timeScale(d3.time.day.floor(new Date(d.joined))) + "px" },
  left: function(d,i) {
    var day = d3.time.day.floor(new Date(d.joined));
    var x = dayBuckets[day].indexOf(d) * rectWidth
    return x + "px"
  },
  width: rectWidth + "px",
  height: rectHeight + "px"
})
.style("display", "none")
.append("img")
.attr({
  src: function(d) { return baseAvatarUrl + d.avatar },
  width: rectWidth,
  height: rectHeight,
  title: function(d) { return d.name }
})





display.on("scroll", scroller);
//scroller()
function scroller() {
  var scroll = this.scrollTop || 0;
  var y0 = timeScale.invert(scroll - 100);
  var y1 = timeScale.invert(scroll + height);//calculate a screen's worth of height
  var filtered = memberDims.joined.filter([y0, y1]).top(Infinity)
  
  var faces = bardiv.selectAll(".face")
  .data(filtered, function(d) { return d.id })
  
  faces
  .style("display", "")
  faces.exit()
  .style("display", "none")
  
  //console.log(y);
}


meetups.json

[{"id":"52020632","name":"Discuss Transitions","venue":"Epicenter Cafe","time":1329442200000},{"id":"53698992","name":"Open Data Hacking at the Library","venue":"Sf public Library Main Branch","time":1330643700000},{"id":"55266432","name":"Getting your Data Drivers License","venue":"swissnex San Francisco ","time":1331863200000},{"id":"57477392","name":"Getting Started with Nutrition and BART","venue":"Nokia Research Center Palo Alto","time":1333503000000},{"id":"64825422","name":"Visualization Open Mic","venue":"BitTorrent","time":1337824800000},{"id":"84262482","name":"Open Data Hacking at the Library","venue":"Sf public Library Main Branch","time":1349472600000},{"id":"102356032","name":"d3.selectAll('meetup').data([2013]).enter()","venue":"Trulia","time":1361500200000},{"id":"51422112","name":".enter() (the first d3.js user group meeting)","venue":"Epicenter Cafe","time":1328835600000},{"id":"52773222","name":"Real-time Dashboards","venue":"Boundary HQ","time":1330050600000},{"id":"54700892","name":"Co-Working Session","venue":"Noisebridge","time":1331173800000},{"id":"55699192","name":"Put some d3 source files up on the screen and discuss","venue":"San Francisco Public Library; Potrero Branch","time":1332281700000},{"id":"58592772","name":"Exploratory Graph Visualization","venue":"Twitter","time":1334280600000},{"id":"57231572","name":"Underscore.js and Canvas","venue":"Tolman Hall, University of California, Berkeley, Berkeley, CA 94720","time":1335313800000},{"id":"63143652","name":"D3 BOF at Fluent Conference 2012","venue":"Hilton Hotel","time":1338346800000},{"id":"67903012","name":"Visual Perception and Illusions","venue":"Groupon","time":1339723800000},{"id":"74765322","name":"d3 goes mobile","venue":"Twitter","time":1344562200000},{"id":"75754562","name":"Rackspace Visualization Hack Day","venue":"Rackspace San Francisco","time":1346428800000},{"id":"84485982","name":"Data geography with d3.geo","venue":"RocketSpace Inc","time":1350610200000},{"id":"102072932","name":"Urban Data Challenge Kick-off","venue":"swissnex San Francisco ","time":1360204200000},{"id":"103428452","name":"Urban Data Hackathon","venue":"Gray Area Foundation for the Arts (GAFFTA)","time":1361642400000},{"id":"111696362","name":"Urban Data Challenge Awards","venue":"swissnex San Francisco ","time":1365271200000}]

style.css

#display {
  overflow:scroll;
}

.facebar {
  position:absolute;
  width: 100px;
  left: 10px;
  display:block;
}

.bar {
  position:absolute;
  border: 1px solid;
}
.face {
  position:absolute;

}

div.node {
  position:absolute;
}

.meetup {
  position:absolute;
  background: #ffffff;
  width: 100px;
  display:block;

}
.meetup-desc {
  position:relative;
  background: rgba(244, 244, 244, 0.51);
  padding-right: 20px;
  text-align:right;
  font-size: 12px;
  font-family: "Helvetica Neue", Helvetica;
  line-height: 22px;
}
.meetup-desc .name {
  font-weight: 600;
  font-size: 14px;
}
.active-meetup {
  stroke: #ff0000;
}