Browse Source

Add support for axis.x.tick.multilineMax (#2364)

* Add support for axis.x.tick.multiline.max

* Add String.padEnd polyfill

* Apply code review suggestions

* Add documentation for `axis.x.tick.multiline`

* Add documentation for `axis.x.tick.multilineMax`
pull/2368/head
João Morais 7 years ago committed by Yoshiya Hinosawa
parent
commit
2ca3be33af
  1. 39
      docs/reference.html.haml
  2. 25
      spec/axis-spec.js
  3. 27
      src/axis.js
  4. 1
      src/config.js
  5. 21
      src/polyfill.js

39
docs/reference.html.haml

@ -79,6 +79,7 @@
= partial :reference_menu_item, locals: { id: 'axis.x.tick.rotate' } = partial :reference_menu_item, locals: { id: 'axis.x.tick.rotate' }
= partial :reference_menu_item, locals: { id: 'axis.x.tick.outer' } = partial :reference_menu_item, locals: { id: 'axis.x.tick.outer' }
= partial :reference_menu_item, locals: { id: 'axis.x.tick.multiline' } = partial :reference_menu_item, locals: { id: 'axis.x.tick.multiline' }
= partial :reference_menu_item, locals: { id: 'axis.x.tick.multilineMax' }
= partial :reference_menu_item, locals: { id: 'axis.x.tick.width' } = partial :reference_menu_item, locals: { id: 'axis.x.tick.width' }
= partial :reference_menu_item, locals: { id: 'axis.x.max' } = partial :reference_menu_item, locals: { id: 'axis.x.max' }
= partial :reference_menu_item, locals: { id: 'axis.x.min' } = partial :reference_menu_item, locals: { id: 'axis.x.min' }
@ -1655,7 +1656,43 @@
%section %section
%h3 %h3
= partial :reference_item_link, locals: { id: 'axis.x.tick.multiline' } = partial :reference_item_link, locals: { id: 'axis.x.tick.multiline' }
%p not yet %p Enable multiline.
%br
%p If this option is set <code>true</code>, when a tick's text on the x-axis is too long, it splits the text into multiple lines in order to avoid text overlapping.
%h5 Default:
<code>false</code>
%h5 Format:
%div.sourcecode
%pre
%code.html.javascript
axis: {
&nbsp;&nbsp;x: {
&nbsp;&nbsp;&nbsp;&nbsp;tick: {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;multiline: true
&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
}
%hr
%section
%h3
= partial :reference_item_link, locals: { id: 'axis.x.tick.multilineMax' }
%p If this option is set and is above <code>0</code>, the number of lines will be adjusted to less than this value and tick's text is ellipsified.
%br
%h5 Default:
<code>0</code>
%h5 Format:
%div.sourcecode
%pre
%code.html.javascript
axis: {
&nbsp;&nbsp;x: {
&nbsp;&nbsp;&nbsp;&nbsp;tick: {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;multiline: true,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;multilineMax: 2,
&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
}
%hr %hr
%section %section

25
spec/axis-spec.js

@ -541,6 +541,31 @@ describe('c3 chart axis', function () {
}); });
}); });
}); });
describe('with multilineMax', function() {
beforeAll(function() {
args.axis.x.tick = {
multiline: true,
multilineMax: 2,
};
});
it('should ellipsify x tick properly', function() {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick');
var tspans = tick.selectAll('tspan');
var expectedTickText = [
'this is a very long',
'tick text on categ...',
];
expect(tspans.size()).toBe(2);
tspans.each(function (d, i) {
var tspan = d3.select(this);
expect(tspan.text()).toBe(expectedTickText[i]);
});
});
});
}); });
}); });

27
src/axis.js

@ -108,6 +108,11 @@ c3_axis_internal_fn.isVertical = function () {
c3_axis_internal_fn.tspanData = function (d, i, scale) { c3_axis_internal_fn.tspanData = function (d, i, scale) {
var internal = this; var internal = this;
var splitted = internal.params.tickMultiline ? internal.splitTickText(d, scale) : [].concat(internal.textFormatted(d)); var splitted = internal.params.tickMultiline ? internal.splitTickText(d, scale) : [].concat(internal.textFormatted(d));
if (internal.params.tickMultiline && internal.params.tickMultilineMax > 0) {
splitted = internal.ellipsify(splitted, internal.params.tickMultilineMax);
}
return splitted.map(function (s) { return splitted.map(function (s) {
return { index: i, splitted: s, length: splitted.length }; return { index: i, splitted: s, length: splitted.length };
}); });
@ -147,6 +152,27 @@ c3_axis_internal_fn.splitTickText = function (d, scale) {
return split(splitted, tickText + ""); return split(splitted, tickText + "");
}; };
c3_axis_internal_fn.ellipsify = function(splitted, max) {
if (splitted.length <= max) {
return splitted;
}
var ellipsified = splitted.slice(0, max);
var remaining = 3;
for (var i = max-1 ; i >= 0 ; i--) {
var available = ellipsified[i].length;
ellipsified[i] = ellipsified[i].substr(0, available-remaining).padEnd(available, '.');
remaining -= available;
if (remaining <= 0) {
break;
}
}
return ellipsified;
};
c3_axis_internal_fn.updateTickLength = function () { c3_axis_internal_fn.updateTickLength = function () {
var internal = this; var internal = this;
internal.tickLength = Math.max(internal.innerTickSize, 0) + internal.tickPadding; internal.tickLength = Math.max(internal.innerTickSize, 0) + internal.tickPadding;
@ -421,6 +447,7 @@ c3_axis_fn.getXAxis = function getXAxis(scale, orient, tickFormat, tickValues, w
isCategory: $$.isCategorized(), isCategory: $$.isCategorized(),
withOuterTick: withOuterTick, withOuterTick: withOuterTick,
tickMultiline: config.axis_x_tick_multiline, tickMultiline: config.axis_x_tick_multiline,
tickMultilineMax: config.axis_x_tick_multiline ? Number(config.axis_x_tick_multilineMax) : 0,
tickWidth: config.axis_x_tick_width, tickWidth: config.axis_x_tick_width,
tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate, tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate,
withoutTransition: withoutTransition, withoutTransition: withoutTransition,

1
src/config.js

@ -107,6 +107,7 @@ c3_chart_internal_fn.getDefaultConfig = function () {
axis_x_tick_rotate: 0, axis_x_tick_rotate: 0,
axis_x_tick_outer: true, axis_x_tick_outer: true,
axis_x_tick_multiline: true, axis_x_tick_multiline: true,
axis_x_tick_multilineMax: 0,
axis_x_tick_width: null, axis_x_tick_width: null,
axis_x_max: undefined, axis_x_max: undefined,
axis_x_min: undefined, axis_x_min: undefined,

21
src/polyfill.js

@ -871,4 +871,25 @@ if (!Function.prototype.bind) {
} }
}()); }());
// String.padEnd polyfill for IE11
//
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
if (!String.prototype.padEnd) {
String.prototype.padEnd = function padEnd(targetLength,padString) {
targetLength = targetLength>>0; //floor if number or convert non-number to 0;
padString = String((typeof padString !== 'undefined' ? padString : ' '));
if (this.length > targetLength) {
return String(this);
}
else {
targetLength = targetLength-this.length;
if (targetLength > padString.length) {
padString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed
}
return String(this) + padString.slice(0,targetLength);
}
};
}
/* jshint ignore:end */ /* jshint ignore:end */

Loading…
Cancel
Save