block by mhkeller 4618211

Sample d3 gantt chart, sorting works, filtering broken

Full Screen

index.html

  <title>Ganttttttttttttt</title>
  <script src="//d3js.org/d3.v3.min.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
	<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js"></script>
	<style>
	.axis path,
	.axis line {
	    fill: none;
	    stroke: none;
	    shape-rendering: crispEdges;
	}

	.axis text {
	    font-family: sans-serif;
	    font-size: 11px;
	}

	.company-bar {
		fill:#fc0;
	}
	.bar-label {
		color:black;
	    font-family: sans-serif;
	    font-size: 11px;
	    text-anchor:end;
	}

	/* HTML Styles*/
	body{
		font-family: "HelveticaNeue-Light", "Helvetica Neue Light","Helvetica Neue", Helvetica,sans-serif;
		font-weight: 300;
	}
	h1,h2,h3,h4,h5,h6,ul{
		margin:0;
	}
	ul li{
		font-size:14px;
	}
	.sort-order{
		font-size:11px;
		letter-spacing:1px;
		font-weight:bold;
	}
	</style>
</head>
<body>
	<h4>Sorters</h4>
	<ul id="btns">
		<li data-sorter="name">
			<a href="#">Sort by name</a>
		</li>
		<li data-sorter="startDate">
			<a href="#">Sort by start date</a>
		</li>
	</ul>
	<script>
		var dataSet = [
			{
				"startDate":"1/1/12",
				"endDate":"2/1/12",
				"sex":"male",
				"companyName":"Vandelay Industries",
			},
			{
				"startDate":"5/2/12",
				"endDate":"4/31/13",
				"sex":"male",
				"companyName":"Dr. Martin Van Nostrand"
			},
			{
				"startDate":"6/14/12",
				"endDate":"8/11/12",
				"sex":"male",
				"companyName":"Uncle Leo"
			},
			{
				"startDate":"3/1/12",
				"endDate":"7/31/12",
				"sex":"female",
				"companyName":"Jackie Chiles"
			},
			{
				"startDate":"3/1/12",
				"endDate":"7/31/12",
				"sex":"female",
				"companyName":"Crazy Joe Davola"
			},
			{
				"startDate":"11/1/12",
				"endDate":"12/31/13",
				"sex":"male",
				"companyName":"Lloyd Braun"
			},
			{
				"startDate":"12/1/11",
				"endDate":"6/15/12",
				"sex":"female",
				"companyName":"Sue Ellen Mishkey"
			}
		]

		var dataInfo = {};

		// D3 requires each object to have a unique key for object constancy
		// //bost.ocks.org/mike/constancy/
		// We can use underscore to create that if we're not sure if they exist in our data
		// Useful if you're updating data quickly (realtime, daily) and need otherwise meaningless uids

		// Also useful for making an associative array for hover info
		for (var datum in dataSet){

			if(_.has(dataSet, datum)){
				var uid = _.uniqueId('a');
				// Add unique id
				dataSet[datum]['uid'] = uid

				// Create associate array
				dataInfo[uid] = dataSet[datum];
			}
		}

		var DATA ={
			dt: dataSet
		}

		var window_width = $(document).width()

		// How many projects do you have?
		var prjs = dataSet.length;

		// Toggler
		var toggler = true;

		// Dimensions
		var bar_height = 20;
		var row_height =  bar_height + 10;
		var vertical_padding = 150
		var bar_start_offset = 40
		var w = window_width - 100;
		var h = prjs * row_height + vertical_padding;

		var svg = d3.select("body")
		            .append("svg")
		            .attr("width", w)  
		            .attr("height", h);

		function getDate(date) {
		    return new Date(date);
		}

		function accessStartDate(d) { return getDate(d.startDate); }
		function accessEndDate(d) { return getDate(d.endDate); }
			
		var min = d3.min(dataSet, accessStartDate);
		var max = d3.max(dataSet, accessEndDate);

		var paddingLeft = 150;
		var paddingTop = 50;

		var xScale = d3.time.scale()
		    .domain([min,max]).nice()
		    .range([paddingLeft, w]);

		var xAxis = d3.svg.axis()
                .scale(xScale)
                .orient("bottom");

		// Lines
	    var line = svg.append("g")
	    	.selectAll("line")
		    	.data(xScale.ticks(10))
		  .enter().append("line")
		    .attr("x1", xScale)
		    .attr("x2", xScale)
		    .attr("y1", paddingTop + 30)
		    .attr("y2", h-50)
		    .style("stroke", "#ccc");

		var y = function(i){
			return i*row_height+paddingTop + bar_start_offset;
		}

		labelY = function(i){
			return i * row_height + paddingTop + bar_start_offset + 13;
		}

		// Company bars
		var bar = svg.selectAll("rect")
			.data(DATA.dt, function(key){return key.uid});

		bar.enter().append("rect")
				.attr("y", function(d, i) { ;return y(i) })
				.attr("x", function(d) { return xScale(getDate(d.startDate))} )
			    .attr("width", function(d) { return (xScale(getDate(d.endDate)) - xScale(getDate(d.startDate))) } )
			    .attr("height", bar_height)
			    .attr("class", "company-bar")
			    .on("mouseover", function(d){d3.select(this).style("fill", "#F5AF00"); getCompanyData(String(d.uid)) })
		        .on("mouseout", function() {d3.select(this).style("fill", "#fc0");});

		// Company Labels
		var label = svg.selectAll("text")
				.data(DATA.dt, function(key){return key.uid});

		label.enter().append("text")
			    .attr("class", "bar-label")
			    // .attr("text-anchor","end")
			    .attr("x", paddingLeft-10)
			    .attr("y", function(d, i) { return labelY(i); })
			    .text(function(d){return d.companyName});

        // Bottom Axis
        var btmAxis = svg.append("g")
            .attr("transform", "translate(0,"+(h - 25)+")")
            .attr("class", "axis")
		    .call(xAxis);

        // Top Axis
        var topAxis = svg.append("g")
            .attr("transform", "translate(0,"+paddingTop+")")
            .attr("class", "axis")
		    .call(xAxis);


	  	function animateRows(){
		    bar.data(DATA.dt, function(d){return d.uid})
		    	.transition()
		      .duration(400)
		      .attr("y", function(d, i) {return y(i) });

		    label.data(DATA.dt, function(d){return d.uid})
		    	.transition()
		      .duration(400)
		      .attr("y", function(d, i) {return labelY(i) });
	  	}

	  	function toggleSort(){
	  		toggler = !toggler;
	  	}

	  	// Name sorters
	  	function sortByName(){
	  		if(!toggler){
	  			sortByNameAsc();
	  		}else{
	  			sortByNameDsc();
	  		}
	  	}
	  	function sortByNameAsc(){
	    	DATA.dt.sort(function(a, b){
			  return d3.ascending(a.companyName, b.companyName);
			})
	  	}
	  	function sortByNameDsc(){
	    	DATA.dt.sort(function(a, b){
			  return d3.descending(a.companyName, b.companyName);
			})
	  	}

	  	// Start Date sorters
	  	function sortByStartDate(){
	  		console.log('b',DATA.dt)
	  		if(!toggler){
	  			sortByStartDateAsc();
	  		}else{
	  			sortByStartDateDsc();
	  		}
	  		console.log('a',DATA.dt)
	  	}
	  	function sortByStartDateAsc(){
	    	DATA.dt.sort(function(a, b){
			  return d3.ascending(getDate(a.startDate), getDate(b.startDate));
			})
	  	}
	  	function sortByStartDateDsc(){
	    	DATA.dt.sort(function(a, b){
			  return d3.descending(getDate(a.startDate), getDate(b.startDate));
			})
	  	}

	  	// Extra text so you know if you're ascending or descending
	  	function sortOrderText(){
	  		if (toggler){
	  			return '<span class="sort-order">(asc)</span>';
	  		}else{
	  			return '<span class="sort-order">(dsc)</span>';
	  		}
	  	}

	  	// Hover info
	  	function getCompanyData(uid){
	  		console.log(dataInfo[uid])

	  	}


	    // Sorters
	    $('#btns li').click( function(){
	    	$('.sort-order').remove();
	    	var sorter = $(this).attr('data-sorter');
	    	toggleSort();

	    	if (sorter == 'name'){
	    		sortByName();
	    	}else if (sorter == 'startDate'){
	    		sortByStartDate()
	    	}
    		animateRows();
    		$(this).append(sortOrderText())
	    });



	  	function filterJSON(json, key, value) {
		  var result = [];
		  for (var index in json) {
		    if (json[index][key] === value) {
		      result.push(json[index]);
		      // result[index] = json[index];
		    }
		  }
		  return result;
		}


		$(document).keyup(function(e) {
			console.log(e.keyCode)
			if (e.keyCode == 27) { /// esc


				var filteredData = filterJSON(dataSet, "sex", 'female');
				// console.log(filteredData)

				DATA.dt = filteredData;

				svg.selectAll('rect')
					.data(DATA.dt, function(d){return d.uid})
						.enter().append("rect")
							.attr("y", function(d, i) { console.log('female',d);return y(i) })
							.attr("x", function(d) { return xScale(getDate(d.startDate))} )
						    .attr("width", function(d) { return (xScale(getDate(d.endDate)) - xScale(getDate(d.startDate))) } )
						    .attr("height", bar_height)
						    .attr("class", "company-bar")
						    .on("mouseover", function(d){d3.select(this).style("fill", "#F5AF00"); getCompanyData(String(d.uid)) })
					        .on("mouseout", function() {d3.select(this).style("fill", "#fc0");});

				svg.selectAll('text')
					.data(DATA.dt, function(d){return d.uid})
					.enter().append("text")
					    .attr("class", "bar-label")
					    .attr("x", paddingLeft-10)
					    .attr("y", function(d, i) { return labelY(i); })
					    .text(function(d){return d.companyName});


				svg.selectAll('rect').data(DATA.dt, function(d){return d.uid})
					.exit().remove();

				svg.selectAll('.bar-label').data(DATA.dt, function(d){return d.uid})
					.exit().remove();
			

	    	}else if(e.keyCode == 16){ // shift
				var filteredData = filterJSON(dataSet, "sex", 'male');
				// console.log(filteredData)

				DATA.dt = filteredData
				svg.selectAll('rect')
					.data(DATA.dt, function(d){return d.uid})
					.enter().append("rect")
						.attr("y", function(d, i) { console.log('male',d);return y(i) })
						.attr("x", function(d) { return xScale(getDate(d.startDate))} )
					    .attr("width", function(d) { return (xScale(getDate(d.endDate)) - xScale(getDate(d.startDate))) } )
					    .attr("height", bar_height)
					    .attr("class", "company-bar")
					    .on("mouseover", function(d){d3.select(this).style("fill", "#F5AF00"); getCompanyData(String(d.uid)) })
				        .on("mouseout", function() {d3.select(this).style("fill", "#fc0");});

				svg.selectAll('text')
					.data(DATA.dt, function(d){return d.uid})
					.enter().append("text")
					    .attr("class", "bar-label")
					    .attr("x", paddingLeft-10)
					    .attr("y", function(d, i) { return labelY(i); })
					    .text(function(d){return d.companyName});

				svg.selectAll('rect').data(DATA.dt, function(d){return d.uid})
					.exit().remove();

				svg.selectAll('.bar-label').data(DATA.dt, function(d){return d.uid})
					.exit().remove();


	    	}else if(e.keyCode == 192){ // tilde
	    		DATA.dt = dataSet;

	    		svg.selectAll('rect')
					.data(DATA.dt, function(d){return d.uid})
					.enter().append("rect")
						.attr("y", function(d, i) { console.log('male',d);return y(i) })
						.attr("x", function(d) { return xScale(getDate(d.startDate))} )
					    .attr("width", function(d) { return (xScale(getDate(d.endDate)) - xScale(getDate(d.startDate))) } )
					    .attr("height", bar_height)
					    .attr("class", "company-bar")
					    .on("mouseover", function(d){d3.select(this).style("fill", "#F5AF00"); getCompanyData(String(d.uid)) })
				        .on("mouseout", function() {d3.select(this).style("fill", "#fc0");});

				svg.selectAll('text')
					.data(DATA.dt, function(d){return d.uid})
					.enter().append("text")
					    .attr("class", "bar-label")
					    .attr("x", paddingLeft-10)
					    .attr("y", function(d, i) { return labelY(i); })
					    .text(function(d){return d.companyName});

				svg.selectAll('rect').data(DATA.dt, function(d){return d.uid})
					.exit().remove();

				svg.selectAll('.bar-label').data(DATA.dt, function(d){return d.uid})
					.exit().remove();
	    	}
	    });

	</script>