Hooray! It now works due to a better understanding of "update" and enter(). The updated Fiddle is http://jsfiddle.net/HHLrF/3/ or read below. Apart from @FernOfTheAndes' help, I found http://bl.ocks.org/mbostock/3808218 helpful.
d3.json("data/tax_stacked.json", function(error, data) {
var mydata = clone(data); // Use a copy of the data to store user's preference.
var desc = function (a,b) { return d3.descending(+a.value, +b.value);}
mydata.sort(desc);
x.domain([0, d3.max(mydata, function(d) { return +d.value * 1.1; })]);
y.domain(mydata.map(function(d) { return d.name; }));
var defs = chart.append("defs");
// Draw the axes
chart.append("g")
.attr("class", "x axis");
chart.append("g")
.attr("class", "y axis");
drawchart();
drawtable();
d3.select("button").on("click",function () {
mydata = clone(data);
mydata.sort(desc);
d3.selectAll("rect.bar")
.data(mydata) // We're rebinding at this level rather than taxes level because the reset value is not propagating down to the <rect class="bar moved"> by itself.
.attr("width", function(d) { console.log(x(d.value)); return x(d.value); });
drawtable();
});
function drawtable() {
// From http://stackoverflow.com/questions/9268645/creating-a-table-linked-to-a-csv-file
var columns = ["name", "value"];
var table = d3.select("#grid");
table.html("");
var thead = table.append("thead"),
tbody = table.append("tbody");
// append the header row
thead.append("tr")
.selectAll("th")
.data(columns)
.enter()
.append("th")
.text(function(column) { return column; });
// create a row for each object in the data
var rows = tbody.selectAll("tr")
.data(mydata)
.enter()
.append("tr");
// create a cell in each row for each column
var cells = rows.selectAll("td")
.data(function(row) {
return columns.map(function(column) {
return {column: column, value: row[column]};
});
})
.enter()
.append("td")
.text(function(d) { return d.value; });
}
function drawchart() {
var drag = d3.behavior.drag()
.on("dragstart", function(){
var where;
d3.select(this).classed({"bar": true, "moved": true});
})
.on("drag", function(d){
where = d3.event.x;
d3.select(this)
.attr("width", where);
d.value = "" + parseInt(x.invert(where));
drawtable();
})
.on("dragend", function(d){
});
var taxes = chart.selectAll(".tax")
.data(mydata);
var taxenter = taxes.enter()
.append("g")
.classed("tax", true);
// Light blue bars for the original budget figures
taxenter.append("rect")
.classed("original", true)
.attr("x", function(d) { return x(0); })
.attr("y", function(d) { return y(d.name); })
.attr("width", function(d) { return x(d.value); })
.attr("height", y.rangeBand())
.attr("rx",0);
// Medium blue bars for the user's budget figures
taxenter.append("rect")
.attr("class", function (d) { return (d.fixed == "y") ? "fixed" : "bar"; })
.attr("x", function(d) { return x(0); })
.attr("y", function(d) { return y(d.name)+1; })
.attr("width", function(d) { return x(d.value); })
.attr("height", y.rangeBand()-1)
.attr("rx",0)
.attr("title", function (d) { return d.value; });
// Draw the axes
chart.selectAll(".x")
.call(xAxis);
chart.select(".y")
.call(yAxis);
// Enable dragging
d3.selectAll(".bar").call(drag);
}
});