<commit_before>define( [
    'jquery',
    'underscore',
    'backbone',
    'd3',
    ],
function ($, _, Backbone, d3) {


  var BarChart = Backbone.View.extend({

  initialize: function(options) {

    var t = this;
    t.config = t.options.graph_config;
    t.raw_data = t.options.raw_data;

    // Transform raw data to format needed by D3.
    t.data = t.map_raw_data(t.raw_data, t.config.label)

    var width = t.$el.width(),
      height = t.$el.height();

    t.x = d3.scale.linear()
        .domain([0, d3.max(t.data, function(d) { return d.val; })])
        .range(["0px", 0.8 * width + 'px']),

    t.chart = d3.select(t.el).append("div")
      .attr("class", "qgr-graph-barchart")
      .style("padding-top", height/3 + 'px');

    t.chart.selectAll("div")
      .data(t.data)
      .enter().append("div")
      .style("width", function(d) { return t.x(d.val); })
      .text(function(d) { return d.label + ': ' + d.val; });

  },

  update: function(raw_data){

    var t = this;

    t.raw_data = raw_data;

    t.data = t.map_raw_data(t.raw_data, t.config.label)

    var bar = t.chart.selectAll("div")
      .data(t.data)

    bar
      .enter()
      .append("div")
      .style("width", 0)
      .transition()
      .duration(500)
      .style("width", function(d) { return t.x(d.val); })
      .text(function(d) { return d.label + ': ' + d.val; });

    bar
      .transition()
      .style("width", function(d) { return t.x(d.val); })
      .text(function(d) { return d.label + ': ' + d.val; });

    bar
      .exit()
      .transition()
      .duration(500)
      .style("width", "0px")
      .remove()

  },

  map_raw_data: function(raw_data, label_col) {
    return _.map(raw_data, function(row) {
      return {
        val: row.val,
        label: row[label_col]
      };
    });
  }
<commit_msg>Always keep bars stacked in order of initial data and transition in/out smoothly<commit_after>define( [
    'jquery',
    'underscore',
    'backbone',
    'd3',
    ],
function ($, _, Backbone, d3) {


  var BarChart = Backbone.View.extend({

  initialize: function(options) {

    var t = this;
    t.config = t.options.graph_config;
    t.raw_data = t.options.raw_data;

    // Transform raw data to format needed by D3.
    t.data = t.map_raw_data(t.raw_data, t.config.label)
    t.init_labels = _.pluck(t.data, 'label')

    var width = t.$el.width(),
      height = t.$el.height();

    t.x = d3.scale.linear()
        .domain([0, d3.max(t.data, function(d) { return d.val; })])
        .range(["0px", 0.8 * width + 'px']),

    t.chart = d3.select(t.el).append("div")
      .attr("class", "qgr-graph-barchart")
      .style("padding-top", height/3 + 'px');

    t.chart.selectAll("div")
      .data(t.data)
      .enter().append("div")
      .style("width", function(d) { return t.x(d.val); })
      .text(function(d) { return d.label + ': ' + d.val; });

  },

  update: function(raw_data){

    var t = this;

    t.raw_data = raw_data;

    t.data = t.map_raw_data(t.raw_data, t.config.label)
    t.data = t.order_by_init_labels(t.data, t.init_labels);

    var bar = t.chart.selectAll("div")
      .data(t.data)

    bar
      .style("visibility", function(d) {
        if (d.val !== 0) {
          return 'visible';
        } else if (d3.select(this).style('visibility') == 'hidden') {
          return 'hidden';
        }
      })
      .text(function(d) {
        if (d.val !== 0) {
          return d.label + ': ' + d.val;
        } else {
          return '';
        }
      })
      .transition()
      .style("width", function(d) {
        return t.x(d.val); })
      .transition()
      // Hide bars that have zero val
      .style("visibility", function(d) {
        if (d.val === 0) {
          return 'hidden'
        }
      })

  },

  map_raw_data: function(raw_data, label_col) {
    return _.map(raw_data, function(row) {
      return {
        val: row.val,
        label: row[label_col]
      };
    });
  },

  order_by_init_labels: function(data, init_labels) {
    return _.map(init_labels, function(label) {
      var val;

      var rows = _.where(data, {label: label});

      if (_.isEmpty(rows)) {
        // If there are no matching rows, then val is zero.
        val = 0;
      } else {
        // Otherwise, there should only be one row, so we take its val.
        val = rows[0].val;
      }

      return {
        label: label,
        val: val
      }
    });
  }

{'fraction_non_alphanumeric': 0.17794316644113667, 'fraction_numerical': 0.008119079837618403, 'mean_word_length': 2.039753255654558, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3679935', 'n_tokens_mistral': 1645, 'n_tokens_neox': 1574, 'n_words': 319}