text: 
  // Chart design based on the recommendations of Stephen Few. Implementation
  // based on the work of Clint Ivy, Jamie Love, and Jason Davies.
  // http://projects.instantcognition.com/protovis/bulletchart/
  nv.models.bulletChart = function() {
      "use strict";
  
      //============================================================
      // Public Variables with Default Settings
      //------------------------------------------------------------
  
      var bullet = nv.models.bullet();
      var tooltip = nv.models.tooltip();
  
      var orient = 'left' // TODO top & bottom
          , reverse = false
          , margin = {top: 5, right: 40, bottom: 20, left: 120}
          , ranges = function(d) { return d.ranges }
          , markers = function(d) { return d.markers ? d.markers : [] }
          , measures = function(d) { return d.measures }
          , width = null
          , height = null
          , tickFormat = null
          , valueFormat = d3.format(',.3f')
          , ticks = null
          , getX = function(d) { return d[0]; }
          , getY = function(d) { return d[1]; }
          , noData = null
          , dispatch = d3.dispatch()
          ;
  
      tooltip
          .duration(0)
          .headerEnabled(false);
  
      function chart(selection) {
          selection.each(function(d, i) {
              var container = d3.select(this);
              nv.utils.initSVG(container);
  
              var availableWidth = nv.utils.availableWidth(width, container, margin),
                  availableHeight = nv.utils.availableHeight(height, container, margin),
                  that = this;
  
              chart.update = function() { chart(selection) };
              chart.container = this;
  
              tooltip.chartContainer(chart.container.parentNode);
  
              // Display No Data message if there's nothing to show.
              if (!d || !d.length) {
                  nv.utils.noData(chart, container);
                  return chart;
              } else {
                  container.selectAll('.nv-noData').remove();
              }
  
              var rangez = ranges.call(this, d[0], i).slice(),
                  markerz = markers.call(this, d[0], i).slice(),
                  measurez = measures.call(this, d[0], i).slice();
  
              // Setup containers and skeleton of chart
              var wrap = container.selectAll('g.nv-wrap.nv-bulletChart').data(d);
              var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bulletChart');
              var gEnter = wrapEnter.append('g');
              var g = wrap.select('g');
  
              gEnter.append('g').attr('class', 'nv-bulletWrap');
              gEnter.append('g').attr('class', 'nv-titles');
  
              wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  
              // Compute the new x-scale.
              var x1 = d3.scale.linear()
                  .domain(
                      d3.extent(
  
                          d3.merge([
                              bullet.forceX(),
                              d3.extent(rangez, bullet.y()),
                              d3.extent(markerz, bullet.y()),
                              [d3.sum(measurez, bullet.y())]
                              ])
                      )
                  )  // TODO: need to allow forceX and forceY, and xDomain, yDomain
                  .range(reverse ? [availableWidth, 0] : [0, availableWidth]);
  
              // Retrieve the old x-scale, if this is an update.
              var x0 = this.__chart__ || d3.scale.linear()
                  .domain([0, Infinity])
                  .range(x1.range());
  
              // Stash the new scale.
              this.__chart__ = x1;
  
              //var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)
              //    w1 = function(d) { return Math.abs(x1(d) - x1(0)) };
  
              var title = gEnter.select('.nv-titles').append('g')
                  .attr('text-anchor', 'end')
                  .attr('transform', 'translate(-6,' + (height - margin.top - margin.bottom) / 2 + ')');
              title.append('text')
                  .attr('class', 'nv-title')
                  .text(function(d) { return d.title; });
  
              title.append('text')
                  .attr('class', 'nv-subtitle')
                  .attr('dy', '1em')
                  .text(function(d) { return d.subtitle; });
  
              bullet
                  .width(availableWidth)
                  .height(availableHeight);
  
              var bulletWrap = g.select('.nv-bulletWrap');
              d3.transition(bulletWrap).call(bullet);
  
              // Compute the tick format.
              var format = tickFormat || x1.tickFormat( availableWidth / 100 );
  
              tooltip.valueFormatter(valueFormat);
  
              // Update the tick groups.
              var tick = g.selectAll('g.nv-tick')
                  .data(x1.ticks( ticks ? ticks : (availableWidth / 100) ), function(d) {
                      return this.textContent || format(d);
                  });
  
              // Initialize the ticks with the old scale, x0.
              var tickEnter = tick.enter().append('g')
                  .attr('class', 'nv-tick')
                  .attr('transform', function(d) { return 'translate(' + x0(d) + ',0)' })
                  .style('opacity', 1e-6);
  
              tickEnter.append('line')
                  .attr('y1', availableHeight)
                  .attr('y2', availableHeight + 6);
  
              tickEnter.append('text')
                  .attr('text-anchor', 'middle')
                  //.attr('dy', '1em')
                  .attr('y', availableHeight + 7)
                  .text(format);
  
              // Transition the updating ticks to the new scale, x1.
              var tickUpdate = /*d3.transition*/(tick)
                  .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' })
                  .style('opacity', 1);
  
              tickUpdate.select('line')
                  .attr('y1', availableHeight)
                  .attr('y2', availableHeight + 10);
  
              tickUpdate.select('text')
                  .attr('y', availableHeight + 10);
  
              // Transition the exiting ticks to the new scale, x1.
              /*d3.transition*/(tick.exit())
                  .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' })
                  .style('opacity', 1e-6)
                  .remove();
          });
  
          d3.timer.flush();
          return chart;
      }
  
      //============================================================
      // Event Handling/Dispatching (out of chart's scope)
      //------------------------------------------------------------
  
      bullet.dispatch.on('elementMouseover.tooltip', function(evt) {
          evt['series'] = {
              key: evt.label,
              value: Math.abs(evt.value),
              color: evt.color
          };
          tooltip.data(evt).hidden(false);
      });
  
      bullet.dispatch.on('elementMouseout.tooltip', function(/*evt*/) {
          tooltip.hidden(true);
      });
  
      bullet.dispatch.on('elementMousemove.tooltip', function(/*evt*/) {
          tooltip();
      });
  
      //============================================================
      // Expose Public Variables
      //------------------------------------------------------------
  
      chart.bullet = bullet;
      chart.dispatch = dispatch;
      chart.tooltip = tooltip;
  
      chart.options = nv.utils.optionsFunc.bind(chart);
  
      chart._options = Object.create({}, {
          // simple options, just get/set the necessary values
          ranges:      {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good)
          markers:     {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal)
          measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast)
          width:    {get: function(){return width;}, set: function(_){width=_;}},
          height:    {get: function(){return height;}, set: function(_){height=_;}},
          tickFormat:    {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}},
          valueFormat:    {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},
          ticks:    {get: function(){return ticks;}, set: function(_){ticks=_;}},
          noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  
          // options that require extra logic in the setter
          margin: {get: function(){return margin;}, set: function(_){
              margin.top    = _.top    !== undefined ? _.top    : margin.top;
              margin.right  = _.right  !== undefined ? _.right  : margin.right;
              margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
              margin.left   = _.left   !== undefined ? _.left   : margin.left;
          }},
          orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom
              orient = _;
              reverse = orient == 'right' || orient == 'bottom';
          }}
      });
  
      nv.utils.inheritOptions(chart, bullet);
      nv.utils.initOptions(chart);
  
      return chart;
  };
  
  
  