score:1

Accepted answer

The way the data is being bound to the rects is incorrect:

var levels = levelsHolder.selectAll('rect.square-levels')
.data(data[key])

results in assigning data["Object one"], then data["Object two"] and so on which enters rects for just data["Object one"] in the first iteration i.e. 3 rects and as there's no update method used, the rects stay as they are resulting in 3 rectangles corresponding to the data["Object one"] array elements.

A solution would be to use the data's keys and map the array's first elements as follows:

var levels = levelsHolder.selectAll('rect.square-levels')
.data(Object.keys(data).map(function(k) { return data[k][0]; }))

Now, I'm being nice and providing you the function for the button click as well (just kidding). Anyway, I'm using two variables "initial" and "max" which goes from 0 through maximum array length in the data and accordingly changes the bound data to the rects. And yes, it can be done using underscore.js as well but I didn't find the need of it here.

Button on click:

d3.select('#myButton').on('click', function() {
   initial++;
   if(initial > max) { initial = 0; }
   levels.data(Object.keys(data).map(function(k) { return data[k][initial]; }));

   drawSquares();
});

Here's a code snippet using the above logic (its not the best of logics but you can change it as per your requirements):

var data= {
	"Object one":[
		{"date":"2010",
		 "value":"80",},
		{"date":"2011",
		 "value":"94",},
		{"date":"2012",
		 "value":"50",},
	],
  	"Object two":[
		{"date":"2010",
		 "value":"104",},
		{"date":"2011",
		 "value":"41",},
		{"date":"2012",
		 "value":"92",},
	],
  	"Object three":[
		{"date":"2010",
		 "value":"75",},
		{"date":"2011",
		 "value":"43",},
		{"date":"2012",
		 "value":"85",},
	],
   "Object four":[
		{"date":"2010",
		 "value":"75",},
		{"date":"2011",
		 "value":"43",},
		{"date":"2012",
		 "value":"85",},
	]
}


  var margin = {top: 30, right: -3, bottom: 30, left:0},
  width = parseInt(d3.select('#holder').style('width'),10)
  width = width - margin.left - margin.right,
  height = width/2;
  
  var initial = 0, max = data['Object one'].length-1;

  var mainChartSVG = d3.select('#holder')
    .append('svg')
    .attr('width', width)
    .attr('height', height)

  var frameHolder = mainChartSVG.append('g')
    .classed('holder-frames',true);

  // Draw squares to show levels

  var maxValue = d3.max(data, function(d){
    return d.value;
  });

  var valueScale = d3.scale.linear()
    .domain([0,100])
    .range([50,0]);

  var levelsHolder = mainChartSVG.append('g')
    .classed('holder-levels',true);
    
  var levels = levelsHolder.selectAll('rect.square-levels')
    .data(Object.keys(data).map(function(k) { return data[k][initial]; }))
    .enter().append('rect')
    .classed('square-levels', true);
    
	function drawSquares() {
      levels
        .attr({
          x: function(d, i){
             return i % 5 * width/5
          },
          y: function(d, i){
             return valueScale(d.value)+(Math.floor(i / 5) * width/5)
          },
        width: width/5-3,
        height: function(d) {
          return (width/5-3)-valueScale(d.value) ;
        },
        fill:"red",
        class: function(d) { return d.value; }
    })
}
drawSquares();

var frameHolder = mainChartSVG.append('g')
    .classed('holder-frames',true);

  var keyarray = Object.keys(data)

  var frames = frameHolder.selectAll('rect.square-frame')
    .data(keyarray)
    .enter().append('rect')
    .classed('square-frame', true)
    .attr({
      x:function(d, i){
        //console.log(d, "D VALUE")
        return i % 5 * (width/5 )
      },
      y:function(d, i){
        return Math.floor(i / 5) * (width/5 )
      },
      width: width/5-3,
      height: width/5-3,
    })

d3.select('#myButton').on('click', function() {
	initial++;
  if(initial > max) { initial = 0; }
  levels.data(Object.keys(data).map(function(k) { return data[k][initial]; }));
  
	drawSquares();
});
body{
  background-color:white;
}

.square-frame{
  stroke: #38434f;
  fill: none;
}

a {
  text-decoration: none;
  display: inline-block;
  padding: 3px 8px;
  margin-bottom: 2em;
}

a:hover {
  background-color: gray;
  color: black;
}

#myButton {
  background-color: #e5e5e5;
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<a href="#" id="myButton">&#8250;</a>
<div id="holder"></div>

Hope this helps. Let me know if you come across any questions.


Related Query

More Query from same tag