@@ -1163,6 +1163,20 @@ function formatCategory(ax, out) {
11631163 var tt = ax . _categories [ Math . round ( out . x ) ] ;
11641164 if ( tt === undefined ) tt = '' ;
11651165 out . text = String ( tt ) ;
1166+
1167+ // Setup ticks and grid lines boundaries
1168+ // at 1/2 a 'category' to the left/bottom
1169+ if ( ax . tickson === 'boundaries' ) {
1170+ var inbounds = function ( v ) {
1171+ var p = ax . l2p ( v ) ;
1172+ return p >= 0 && p <= ax . _length ? v : null ;
1173+ } ;
1174+
1175+ out . xbnd = [
1176+ inbounds ( out . x - 0.5 ) ,
1177+ inbounds ( out . x + ax . dtick - 0.5 )
1178+ ] ;
1179+ }
11661180}
11671181
11681182function formatLinear ( ax , out , hover , extraPrecision , hideexp ) {
@@ -1621,18 +1635,18 @@ axes.drawOne = function(gd, ax, opts) {
16211635 var tickVals ;
16221636 var gridVals ;
16231637
1624- if ( ax . tickson === 'boundaries' ) {
1625- // draw ticks and grid lines 1/2 a 'category' to the left,
1626- // add one item at axis tail
1627- var valsBoundaries = vals . map ( function ( d ) {
1628- var d2 = Lib . extendFlat ( { } , d ) ;
1629- d2 . x -= 0.5 ;
1630- return d2 ;
1631- } ) ;
1632- // not used for labels; no need to worry about the other tickTextObj keys
1633- var d2 = Lib . extendFlat ( { } , vals [ vals . length - 1 ] ) ;
1634- d2 . x + = 0.5 ;
1635- valsBoundaries . push ( d2 ) ;
1638+ if ( ax . tickson === 'boundaries' && vals . length ) {
1639+ // valsBoundaries is not used for labels;
1640+ // no need to worry about the other tickTextObj keys
1641+ var valsBoundaries = [ ] ;
1642+ var _push = function ( d , bndIndex ) {
1643+ var xb = d . xbnd [ bndIndex ] ;
1644+ if ( xb !== null ) {
1645+ valsBoundaries . push ( Lib . extendFlat ( { } , d , { x : xb } ) ) ;
1646+ }
1647+ } ;
1648+ for ( i = 0 ; i < vals . length ; i ++ ) _push ( vals [ i ] , 0 ) ;
1649+ _push ( vals [ i - 1 ] , 1 ) ;
16361650
16371651 valsClipped = axes . clipEnds ( ax , valsBoundaries ) ;
16381652 tickVals = ax . ticks === 'inside' ? valsClipped : valsBoundaries ;
0 commit comments