title: Create a smooth draggable bar-graph using d3js
body: <p>I am attempting to create a bar graph that can be updated by dragging the bars. I have been able to create such a graph but the dragging is not smooth. View my attempt in <a href="http://jsfiddle.net/p0rphda3/2/" rel="nofollow">fiddle</a></p>
  
  <p>Here is my code: </p>
  
  <pre><code>var data = [{x:-6.1, y: "I"}, {x:-4.5, y: "H"}, {x: -0.4, y: "G"},{x:0.8, y: "F"}, {x:3.8, y: "E"}, {x: 5.3, y: "D"}];
  
  drawDraggableBarGraph= function(data, drawSmoothCurve, element) {
    var bar, barHeight, datae, h, height, j, len, lineFunc, margin, objects, parsedX, svg, w, width, xAxis, xMax, xMin, xScale;
    $(element).empty();
  
    svg = d3.select(element).append("svg");
  
    margin = {
      top: 10,
      bottom: 20,
      left: 30,
      right: 10
    };
  
    w = $(element).width();
    h = 200;
    width = w - margin.left - margin.right;
    height = h - margin.top - margin.bottom;
  
    for (j = 0, len = data.length; j &lt; len; j++) {
      datae = data[j];
      parsedX = parseFloat(datae.x);
      datae.x = parsedX;
    }
  
    svg = svg.attr("width", w).attr("height", h).append("g").attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
  
    xMin = d3.min(data, function(d) {
      return d.x;
    });
    xMax = d3.max(data, function(d) {
      return d.x;
    });
  
    xScale = d3.scale.linear().domain([xMin &gt; 0 ? xMin * 0.95 : xMin * 1.05, xMax * 1.05]).range([0, width]);
  
    barHeight = (height / data.length) * 0.9;
  
    xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickSize(-height);
    svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(xAxis);
  
    objects = svg.append('svg').attr('width', width).attr('height', height);
  
    bar = objects.selectAll("g").data(data).enter().append("g").attr("transform",       function(d, i) {
      return "translate(0," + (i * barHeight + height * 0.05) + ")";
    }).attr('fill', function(d, i) {
      return d3.scale.category20().range()[i];
    });
  
    bar.append('rect').attr("x", 0).attr('width', width).attr('height', barHeight - 1).attr('fill', 'transparent');
  
    bar.append("rect").attr("x", function(d) {
      if (d.x &gt; 0) {
        return xScale(0);
      } else {
        return xScale(d.x);
      }
    }).attr("width", function(d) {
      if (d.x &gt; 0) {
        return xScale(d.x) - xScale(0);
      } else {
        return xScale(0) - xScale(d.x);
      }
    }).attr("height", barHeight - 1).attr('class', function(d) {
      return "drag-bar-" + d.y;
    });
  
    bar.on('mouseover', function(d) {
      jQuery("line.default-hidden").hide();
      return $(this).children('line').show();
    }).on('mouseout', function(d) {
      return jQuery("line.default-hidden").hide();
    });
  
    bar.append("text").attr("dy", ".75em").attr("y", barHeight / 2 - 7).attr("x", function(d) {
      if (d.x &gt; 0) {
        return xScale(0) - 10;
      } else {
        return xScale(0) + 10;
      }
    }).attr("text-anchor", "middle").text(function(d) {
      return d.y;
    });
  
    if (drawSmoothCurve) {
  
      // Try commenting out from here 
      lineFunc = d3.svg.line().x(function(d) {
        return xScale(d.x);
      }).y((function(_this) {
        return function(d, i) {
          return i * barHeight + barHeight / 2 + height * 0.05;
        };
      })(this)).interpolate("basis");
  
      objects.append("path").attr("d", lineFunc(data)).attr("stroke", "#666666").attr("stroke-width", 1).attr("fill", "none");
      // Till here
  
      bar.append('line').attr('x1', function(d) {
        return xScale(d.x);
      }).attr('x2', function(d) {
        return xScale(d.x);
      }).attr('y1', -1).attr('y2', barHeight).attr('stroke', 'black').attr('stroke-width', '6').attr('class', function(d) {
        return "default-hidden drag-line-" + d.y;
      }).on("mousedown", function(d) {
        return d3.select(this).classed('drag-enabled', true);
      }).on('mousemove', function(d) {
        var newX, p;
        if ($(this).attr('class').indexOf('drag-enabled') &lt; 0) {
          return;
        }
        p = d3.mouse(this);
        newX = p[0];
        return d3.select(this).attr('x1', newX).attr('x2', newX);
      }).on('mouseup', (function(_this) {
        return function(d) {
          var attrY, classList, k, klass, l, len1, len2, newBarX;
          d3.select(this).classed('drag-enabled', false);
          newBarX = d3.mouse(this)[0];
          classList = this.classList;
          attrY = null;
          for (k = 0, len1 = classList.length; k &lt; len1; k++) {
            klass = classList[k];
            if (klass.indexOf('drag-line') &gt;= 0) {
              attrY = klass.slice(klass.lastIndexOf('-') + 1);
            }
          }
          data = data;
          for (l = 0, len2 = data.length; l &lt; len2; l++) {
            datae = data[l];
            if (datae.y === attrY) {
              datae.x = xScale.invert(newBarX).toFixed(2);
            }
          }
          return drawDraggableBarGraph(data, true,".sliding-bar");
        };
      })(this));
    }
  }
  
  drawDraggableBarGraph(data, true,".sliding-bar");
  </code></pre>
  
  <p>I am trying to make the process of updating values user-friendly but halts while dragging kills it somehow. </p>
  
  <p>Any suggestions to make it smooth</p>