0

I'm trying to represent a selection sort visually with d3 to show some students and I'm having problems updating the data once the positions swap(I will add the transitions and delays once it's working). The positional attributes don't seem to be working as well, I don't know why, any ideas?. The codepen is here:

HTML:

<div id="canvas">

</div>

CSS:

rect{
  border:1px solid black;
}

JS:

function selectionSort(array,svg){
  //where the index will position
  var positioningIndex=0;
  var aux;
  var minIndex;
  var minVal=Number.MAX_VALUE;

  while(positioningIndex<array.length){
  //get the index of the mínimum
      for(var i=positioningIndex;i<array.length;i++){
        if(array[i]<minVal){
          minIndex=i;
          minVal=array[i];
        }
      }

  //swap the mínimum to the positioningIndex
  aux=array[minIndex];
  array[minIndex]=array[positioningIndex];
  array[positioningIndex]=aux;
  //update visualization 
  svg.selectAll("rect").data(array);  

  minVal=Number.MAX_VALUE;
  ++positioningIndex;
}

  return array;

}


var dataSet=[10,7,8,44];
var svg=d3.select("#canvas").selectAll("rect")
  .append("svg")
    .attr("width", 960)
    .attr("height", 500);

  var rect=svg.data(dataSet)
  .enter()
  .append("rect");


  rect.text(function(el){
    return el;
  })
  .attr("width", 30)
  .attr("height", 30)
.attr("x", function(d, i) {             
                            return i*5;
                        })
                        .attr("y", 30);
  .style("color","green");


array=selectionSort(dataSet,svg);
John
  • 1,711
  • 2
  • 29
  • 42

1 Answers1

0

You've got a lot of mixing up of html and svg elements going on there

First off, your svg element isn't getting appended:

var svg=d3.select("#canvas").selectAll("rect") // <- selectAll("rect") is causing problems
  .append("svg")

No existing rect elements at the start means no svg's getting appended (do you mean to add one for each rect?) Edit: and in fact that one error is the cause of everything that happens afterwards - the selectAll("rect") needs moved to the line where elements are added to the svg - not on the line where the svg itself is added -->

var rect=svg.selectAll("rect").data(dataSet) // rect should really be g
  .enter()
  .append("rect");

Secondly, and because of the above error, the elements called 'rect' that are added (and added directly to the #canvas id div) aren't svg:rect objects - they're just html elements with the name 'rect' - see Is there a way to create your own html tag in HTML5?. The browser just treats them as inline elements, so none of your x's or y's make a difference they just line up one after the other

Finally, if this was svg you wouldn't be able to add text directly to a rect, you'd need to use a group (g) element and add both rect and text elements to that to keep them associated, and style("transform", translate(x,y)) the group element to move them around.

var g=svg.selectAll("g").data(dataSet) // <-- now changed from rect
  .enter()
  .append("g") // <-- and here
  .attr ("transform", function(d,i) {
    return "translate("+(i*35)+" 30)";
  })
  ;
  // texts n rects added here
  g.append("text").text(function(el){
    return el;
  })
  .attr("dy", "1em")
g.append("rect")
  .attr("width", 30)
  .attr("height", 30)
;

See http://codepen.io/anon/pen/bwJWEa?editors=1111

Community
  • 1
  • 1
mgraham
  • 6,147
  • 1
  • 21
  • 20
  • Thanks, do you have any specific code suggestion to fix my problem?. I just want one rectangle per position of the array, I need svg rectangles to be created – John Oct 26 '16 at 14:16
  • I think a lot of the problems can be solved by removing the .selectAll("rect") from the var svg line and putting it in the var rect line: e.g. `var rect=svg.selectAll("rect").data(dataSet)`. That gets rid of the "html not svg" issue. Then replace the "rect" with "g" and add rect and text element separately to each group element – mgraham Oct 26 '16 at 14:20