@ons/design-system 72.10.0 → 72.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/char-check-limit/_macro.njk +2 -2
- package/components/char-check-limit/character-check.js +30 -9
- package/components/char-check-limit/character-check.spec.js +1 -1
- package/components/chart/_chart.scss +2 -3
- package/components/chart/_macro.njk +27 -16
- package/components/chart/_macro.spec.js +19 -0
- package/components/chart/bar-chart.js +46 -20
- package/components/chart/chart-constants.js +1 -0
- package/components/chart/chart.js +17 -1
- package/components/chart/common-chart-options.js +57 -28
- package/components/chart/example-column-chart-with-custom-reference-line-value.njk +56 -0
- package/components/chart/example-line-chart-with-custom-reference-line-value.njk +224 -0
- package/components/chart/example-line-chart-with-markers.njk +20 -20
- package/components/chart/example-scatter-chart.njk +4 -4
- package/components/chart/line-chart.js +29 -11
- package/components/chart/range-annotations-options.js +6 -1
- package/components/chart/scatter-chart.js +0 -6
- package/components/chart/specific-chart-options.js +21 -0
- package/components/chart/utilities.js +8 -7
- package/components/checkboxes/_macro.spec.js +1 -1
- package/components/mutually-exclusive/mutually-exclusive.textarea.spec.js +1 -1
- package/components/textarea/_macro.njk +8 -6
- package/components/textarea/_macro.spec.js +12 -8
- package/components/textarea/{example-textarea-with-character-limit.njk → example-textarea-with-character-check.njk} +3 -1
- package/css/main.css +1 -1
- package/js/main.js +0 -1
- package/package.json +14 -14
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +1 -1
- package/components/char-check-limit/character-limit.js +0 -55
- package/components/textarea/textarea.dom.js +0 -12
- package/components/textarea/textarea.spec.js +0 -98
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
class="ons-input__limit ons-u-fs-s--b ons-u-d-no ons-u-mt-2xs"
|
|
9
9
|
data-charcount-singular="{{ params.charCountSingular }}"
|
|
10
10
|
data-charcount-plural="{{ params.charCountPlural }}"
|
|
11
|
-
data-charcount-limit-singular="{{ params.charCountOverLimitSingular }}"
|
|
12
|
-
data-charcount-limit-plural="{{ params.charCountOverLimitPlural }}"
|
|
11
|
+
data-charcount-limit-singular="{{ params.charCountOverLimitSingular | default("You have exceeded the character limit by {x} character") }}"
|
|
12
|
+
data-charcount-limit-plural="{{ params.charCountOverLimitPlural | default("You have exceeded the character limit by {x} characters") }}"
|
|
13
13
|
>
|
|
14
14
|
</span>
|
|
15
15
|
{% endmacro %}
|
|
@@ -6,9 +6,18 @@ const attrCharCheckVal = 'data-char-check-num';
|
|
|
6
6
|
|
|
7
7
|
export default class CharCheck {
|
|
8
8
|
constructor(context) {
|
|
9
|
-
this.
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
this.tagName = context.tagName;
|
|
10
|
+
|
|
11
|
+
// Handle either an input directly or a container with an input inside
|
|
12
|
+
if (this.tagName.toLowerCase() === 'input' || this.tagName.toLowerCase() === 'textarea') {
|
|
13
|
+
this.input = context;
|
|
14
|
+
} else {
|
|
15
|
+
this.input = context.querySelector('input');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Find the button: if input is passed directly, look at its parent
|
|
19
|
+
let parent = this.input.parentNode;
|
|
20
|
+
this.button = parent ? parent.querySelector('button') : null;
|
|
12
21
|
this.checkElement = document.getElementById(this.input.getAttribute(attrCharCheckRef));
|
|
13
22
|
this.checkVal = this.input.getAttribute(attrCharCheckVal);
|
|
14
23
|
this.countdown = this.input.getAttribute(attrCharCheckCountdown) || false;
|
|
@@ -22,15 +31,17 @@ export default class CharCheck {
|
|
|
22
31
|
if (this.button) {
|
|
23
32
|
this.setButtonState(this.checkVal);
|
|
24
33
|
}
|
|
34
|
+
|
|
25
35
|
this.input.addEventListener('input', this.updateCheckReadout.bind(this));
|
|
26
36
|
}
|
|
27
37
|
|
|
28
38
|
updateCheckReadout(event, firstRun) {
|
|
29
39
|
const value = this.input.value;
|
|
30
|
-
const remaining = this.checkVal - value
|
|
40
|
+
const remaining = this.checkVal - this.getCharLength(value);
|
|
41
|
+
|
|
31
42
|
// Prevent aria live announcement when component initialises
|
|
32
43
|
if (!firstRun && event.inputType) {
|
|
33
|
-
this.checkElement.setAttribute('aria-live', 'polite');
|
|
44
|
+
this.checkElement.setAttribute('aria-live', [remaining > 0 ? 'polite' : 'assertive']);
|
|
34
45
|
} else {
|
|
35
46
|
this.checkElement.removeAttribute('aria-live');
|
|
36
47
|
}
|
|
@@ -67,13 +78,23 @@ export default class CharCheck {
|
|
|
67
78
|
}
|
|
68
79
|
|
|
69
80
|
setShowMessage(remaining) {
|
|
70
|
-
this.
|
|
71
|
-
|
|
72
|
-
|
|
81
|
+
if (this.tagName.toLowerCase() === 'textarea') {
|
|
82
|
+
// Always display the remaining character message for textarea
|
|
83
|
+
this.checkElement.classList['remove']('ons-u-d-no');
|
|
84
|
+
} else {
|
|
85
|
+
this.checkElement.classList[(remaining < this.checkVal && remaining > 0 && this.countdown) || remaining < 0 ? 'remove' : 'add'](
|
|
86
|
+
'ons-u-d-no',
|
|
87
|
+
);
|
|
88
|
+
}
|
|
73
89
|
}
|
|
74
90
|
|
|
75
91
|
setCheckClass(remaining, element, setClass) {
|
|
76
92
|
element.classList[remaining < 0 ? 'add' : 'remove'](setClass);
|
|
77
|
-
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
getCharLength(text) {
|
|
96
|
+
// line breaks count as two characters as forms convert to \n\r when submitted
|
|
97
|
+
const lineBreaks = (text.match(/\n/g) || []).length;
|
|
98
|
+
return text.length + lineBreaks;
|
|
78
99
|
}
|
|
79
100
|
}
|
|
@@ -192,7 +192,7 @@ describe('script: character-check', () => {
|
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
it('then aria-live attribute should removed', async () => {
|
|
195
|
-
const hasAriaLiveAttribute = await page.$eval('#feedback-
|
|
195
|
+
const hasAriaLiveAttribute = await page.$eval('#feedback-check', (element) => element.hasAttribute('aria-live'));
|
|
196
196
|
expect(hasAriaLiveAttribute).toBe(false);
|
|
197
197
|
});
|
|
198
198
|
});
|
|
@@ -91,15 +91,14 @@
|
|
|
91
91
|
|
|
92
92
|
&-item {
|
|
93
93
|
&--uncertainty {
|
|
94
|
-
width:
|
|
95
|
-
height:
|
|
94
|
+
width: 14px;
|
|
95
|
+
height: 14px;
|
|
96
96
|
background-color: rgb(32 96 149 / 65%);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
&--estimate {
|
|
100
100
|
width: 20px;
|
|
101
101
|
height: 3px;
|
|
102
|
-
border-radius: 2px;
|
|
103
102
|
background-color: #003c57;
|
|
104
103
|
}
|
|
105
104
|
}
|
|
@@ -47,6 +47,9 @@
|
|
|
47
47
|
{% if params.uncertaintyRangeLabel %}
|
|
48
48
|
data-highcharts-uncertainty-range-label="{{ params.uncertaintyRangeLabel }}"
|
|
49
49
|
{% endif %}
|
|
50
|
+
{% if params.yAxis.customReferenceLineValue %}
|
|
51
|
+
data-highcharts-custom-reference-line-value="{{ params.yAxis.customReferenceLineValue }}"
|
|
52
|
+
{% endif %}
|
|
50
53
|
>
|
|
51
54
|
<figure class="ons-chart">
|
|
52
55
|
{{ openingTitleTag | safe }} class="ons-chart__title">{{ params.title }}{{ closingTitleTag | safe }}
|
|
@@ -119,23 +122,31 @@
|
|
|
119
122
|
{% endif %}
|
|
120
123
|
{% if params.chartType in supportedChartTypes %}
|
|
121
124
|
{% set series = [] %}
|
|
125
|
+
{% set lineSeriesCount = 0 %}
|
|
122
126
|
{% for item in params.series %}
|
|
123
|
-
{%
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
"
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
127
|
+
{% if item.type == 'line' and lineSeriesCount > 0 %}
|
|
128
|
+
{# skip extra line series as the DS guidelines only allow for one extra line series #}
|
|
129
|
+
{% else %}
|
|
130
|
+
{%
|
|
131
|
+
set seriesItem = {
|
|
132
|
+
"name": item.name if item.name else '',
|
|
133
|
+
"data": item.data if item.data else [],
|
|
134
|
+
"marker": {
|
|
135
|
+
"enabled": item.marker if item.marker else false
|
|
136
|
+
},
|
|
137
|
+
"dataLabels": {
|
|
138
|
+
"enabled": item.dataLabels if item.dataLabels else false
|
|
139
|
+
},
|
|
140
|
+
"connectNulls": item.connectNulls if item.connectNulls else false,
|
|
141
|
+
"type": item.type if item.type and (item.type == 'line' and params.chartType in supportedChartTypesWithLine) or (item.type == 'scatter' and params.chartType in supportedChartTypesWithScatter) else params.chartType
|
|
142
|
+
}
|
|
143
|
+
%}
|
|
144
|
+
{# Use `set` tag to avoid printing the return value of extend #}
|
|
145
|
+
{% set _ = extend(series, seriesItem) %}
|
|
146
|
+
{% endif %}
|
|
147
|
+
{% if item.type == 'line' %}
|
|
148
|
+
{% set lineSeriesCount = lineSeriesCount + 1 %}
|
|
149
|
+
{% endif %}
|
|
139
150
|
{% endfor %}
|
|
140
151
|
{# Set the legend value to true by default #}
|
|
141
152
|
{% set legendValue = true %}
|
|
@@ -702,6 +702,7 @@ describe('Macro: Chart', () => {
|
|
|
702
702
|
expect($('[data-highcharts-base-chart]').attr('data-highcharts-theme')).toBe('alternate');
|
|
703
703
|
expect($('[data-highcharts-base-chart]').attr('data-highcharts-title')).toBe('Example Column Chart');
|
|
704
704
|
expect($('[data-highcharts-base-chart]').attr('data-highcharts-id')).toBe('column-chart-123');
|
|
705
|
+
expect($('[data-highcharts-base-chart]').attr('data-highcharts-custom-reference-line-value')).toBe('10');
|
|
705
706
|
});
|
|
706
707
|
|
|
707
708
|
test('THEN: it includes the Highcharts JSON config', () => {
|
|
@@ -709,6 +710,24 @@ describe('Macro: Chart', () => {
|
|
|
709
710
|
expect(configScript).toContain('"text":"Y Axis Title"');
|
|
710
711
|
});
|
|
711
712
|
});
|
|
713
|
+
describe('WHEN: more than one line is provided', () => {
|
|
714
|
+
const $ = cheerio.load(
|
|
715
|
+
renderComponent('chart', {
|
|
716
|
+
...EXAMPLE_COLUMN_WITH_LINE_CHART_PARAMS,
|
|
717
|
+
series: [
|
|
718
|
+
...EXAMPLE_COLUMN_WITH_LINE_CHART_PARAMS.series,
|
|
719
|
+
{ name: 'Additional Line', data: [15, 25, 35], type: 'line' },
|
|
720
|
+
{ name: 'Another additional Line', data: [14, 27, 31], type: 'line' },
|
|
721
|
+
],
|
|
722
|
+
}),
|
|
723
|
+
);
|
|
724
|
+
const configScript = $(`script[data-highcharts-config--column-chart-123]`).html();
|
|
725
|
+
|
|
726
|
+
test('THEN: it does not include the additional line series', () => {
|
|
727
|
+
const lineTypeMatches = (configScript.match(/"type":"line"/g) || []).length;
|
|
728
|
+
expect(lineTypeMatches).toBe(1);
|
|
729
|
+
});
|
|
730
|
+
});
|
|
712
731
|
});
|
|
713
732
|
|
|
714
733
|
describe('GIVEN: Params: Legend', () => {
|
|
@@ -70,29 +70,55 @@ class BarChart {
|
|
|
70
70
|
};
|
|
71
71
|
|
|
72
72
|
// Updates the config to move the data labels inside the bars, but only if the bar is wide enough
|
|
73
|
-
// This
|
|
73
|
+
// This also runs when the chart is resized
|
|
74
74
|
postLoadDataLabels = (currentChart) => {
|
|
75
|
-
const insideOptions =
|
|
76
|
-
|
|
77
|
-
};
|
|
78
|
-
const outsideOptions = {
|
|
79
|
-
dataLabels: this.getBarChartLabelsOutsideOptions(),
|
|
80
|
-
};
|
|
81
|
-
|
|
75
|
+
const insideOptions = this.getBarChartLabelsInsideOptions();
|
|
76
|
+
const outsideOptions = this.getBarChartLabelsOutsideOptions();
|
|
82
77
|
currentChart.series.forEach((series) => {
|
|
78
|
+
// If we have a bar chart with an extra line, exit early for the line series
|
|
79
|
+
if (series.type == 'line') {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (series.type == 'scatter') {
|
|
84
|
+
// If we have a bar chart with confidence levels, exit early for the scatter series
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
83
88
|
const points = series.data;
|
|
89
|
+
|
|
84
90
|
points.forEach((point) => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
if (point.dataLabel) {
|
|
92
|
+
// Get the actual width of the data label
|
|
93
|
+
const labelWidth = point.dataLabel.getBBox().width;
|
|
94
|
+
|
|
95
|
+
// Move the data labels inside the bar if the bar is wider than the label plus some padding
|
|
96
|
+
if (point.shapeArgs.height > labelWidth + 5) {
|
|
97
|
+
// Negative values are aligned on the left, positive values on the right
|
|
98
|
+
if (point.y < 0) {
|
|
99
|
+
point.update(
|
|
100
|
+
{
|
|
101
|
+
dataLabels: {
|
|
102
|
+
...insideOptions,
|
|
103
|
+
align: 'left',
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
false,
|
|
107
|
+
);
|
|
108
|
+
} else {
|
|
109
|
+
point.update(
|
|
110
|
+
{
|
|
111
|
+
dataLabels: {
|
|
112
|
+
...insideOptions,
|
|
113
|
+
align: 'right',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
false,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
point.update({ dataLabels: outsideOptions }, false);
|
|
121
|
+
}
|
|
96
122
|
}
|
|
97
123
|
});
|
|
98
124
|
});
|
|
@@ -102,7 +128,6 @@ class BarChart {
|
|
|
102
128
|
|
|
103
129
|
getBarChartLabelsInsideOptions = () => ({
|
|
104
130
|
inside: true,
|
|
105
|
-
align: 'right',
|
|
106
131
|
verticalAlign: 'middle',
|
|
107
132
|
style: {
|
|
108
133
|
color: 'white',
|
|
@@ -114,6 +139,7 @@ class BarChart {
|
|
|
114
139
|
inside: false,
|
|
115
140
|
align: undefined,
|
|
116
141
|
verticalAlign: undefined,
|
|
142
|
+
overflow: 'allow',
|
|
117
143
|
style: {
|
|
118
144
|
textOutline: 'none',
|
|
119
145
|
// The design system does not include a semibold font weight, so we use 700 (bold) as an alternative.
|
|
@@ -65,6 +65,10 @@ class HighchartsBaseChart {
|
|
|
65
65
|
this.commonChartOptions = new CommonChartOptions(this.xAxisTickIntervalDesktop, this.yAxisTickIntervalDesktop);
|
|
66
66
|
this.estimateLineLabel = this.node.dataset.highchartsEstimateLineLabel;
|
|
67
67
|
this.uncertainyRangeLabel = this.node.dataset.highchartsUncertaintyRangeLabel;
|
|
68
|
+
this.customReferenceLineValue = this.node.dataset.highchartsCustomReferenceLineValue
|
|
69
|
+
? parseFloat(this.node.dataset.highchartsCustomReferenceLineValue)
|
|
70
|
+
: undefined;
|
|
71
|
+
|
|
68
72
|
this.specificChartOptions = new SpecificChartOptions(this.theme, this.chartType, this.config);
|
|
69
73
|
this.lineChart = new LineChart();
|
|
70
74
|
this.barChart = new BarChart();
|
|
@@ -93,6 +97,15 @@ class HighchartsBaseChart {
|
|
|
93
97
|
return this.chartType === 'line' ? 0 : this.config.series.filter((series) => series.type === 'line').length;
|
|
94
98
|
};
|
|
95
99
|
|
|
100
|
+
// Used to ensure that extra line series always overlay the column series
|
|
101
|
+
updateExtraLineZIndex = () => {
|
|
102
|
+
this.config.series.forEach((series) => {
|
|
103
|
+
if (series.type === 'line') {
|
|
104
|
+
series.zIndex = this.config.series.length + 1;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
|
|
96
109
|
// Check for the number of extra line series in the config
|
|
97
110
|
checkForExtraScatter = () => {
|
|
98
111
|
return this.chartType === 'scatter' ? 0 : this.config.series.filter((series) => series.type === 'scatter').length;
|
|
@@ -148,7 +161,9 @@ class HighchartsBaseChart {
|
|
|
148
161
|
}
|
|
149
162
|
|
|
150
163
|
if (this.extraLines > 0) {
|
|
164
|
+
this.updateExtraLineZIndex();
|
|
151
165
|
this.config = mergeConfigs(this.config, this.lineChart.getLineChartOptions());
|
|
166
|
+
this.config = mergeConfigs(this.config, this.lineChart.getExtraLineChartOptions(this.config.series.length + 1));
|
|
152
167
|
if (this.chartType === 'column') {
|
|
153
168
|
this.config = mergeConfigs(this.config, columnChartOptions);
|
|
154
169
|
}
|
|
@@ -192,8 +207,9 @@ class HighchartsBaseChart {
|
|
|
192
207
|
this.rangeAnnotations,
|
|
193
208
|
this.rangeAnnotationsOptions,
|
|
194
209
|
this.referenceLineAnnotationsOptions,
|
|
195
|
-
this.
|
|
210
|
+
this.specificChartOptions,
|
|
196
211
|
this.chartType,
|
|
212
|
+
this.customReferenceLineValue,
|
|
197
213
|
);
|
|
198
214
|
|
|
199
215
|
let rules = [
|
|
@@ -113,8 +113,6 @@ class CommonChartOptions {
|
|
|
113
113
|
},
|
|
114
114
|
plotOptions: {
|
|
115
115
|
series: {
|
|
116
|
-
// disables the tooltip on hover
|
|
117
|
-
enableMouseTracking: false,
|
|
118
116
|
animation: false,
|
|
119
117
|
|
|
120
118
|
// disables the legend item hover
|
|
@@ -129,32 +127,19 @@ class CommonChartOptions {
|
|
|
129
127
|
},
|
|
130
128
|
},
|
|
131
129
|
},
|
|
130
|
+
tooltip: {
|
|
131
|
+
animation: false,
|
|
132
|
+
},
|
|
132
133
|
};
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
getOptions = () => this.options;
|
|
136
137
|
|
|
137
|
-
// TODO: A future ticket will add support for other plot lines which are not
|
|
138
|
-
// reference line annotations, and will be styled like the zero line
|
|
139
|
-
// See ticket https://jira.ons.gov.uk/browse/CCB-63
|
|
140
|
-
getPlotLines = () => {
|
|
141
|
-
// Add zero line
|
|
142
|
-
return {
|
|
143
|
-
yAxis: {
|
|
144
|
-
plotLines: [
|
|
145
|
-
{
|
|
146
|
-
color: this.constants.zeroLineColor,
|
|
147
|
-
width: 1.5,
|
|
148
|
-
value: 0,
|
|
149
|
-
zIndex: 2,
|
|
150
|
-
},
|
|
151
|
-
],
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
};
|
|
155
|
-
|
|
156
138
|
getMobileOptions = (xAxisTickInterval, yAxisTickInterval) => {
|
|
157
139
|
return {
|
|
140
|
+
tooltip: {
|
|
141
|
+
enabled: false,
|
|
142
|
+
},
|
|
158
143
|
xAxis: {
|
|
159
144
|
tickInterval: xAxisTickInterval,
|
|
160
145
|
},
|
|
@@ -185,20 +170,64 @@ class CommonChartOptions {
|
|
|
185
170
|
|
|
186
171
|
updateLegendSymbols = (chart) => {
|
|
187
172
|
if (chart.legend.options.enabled) {
|
|
188
|
-
chart.legend.allItems.forEach((item) => {
|
|
173
|
+
chart.legend.allItems.forEach((item, index) => {
|
|
189
174
|
const { legendItem, userOptions } = item;
|
|
190
175
|
const seriesType = userOptions?.type;
|
|
191
|
-
|
|
192
|
-
// if symbol is defined for a line series, it is the marker symbol
|
|
193
|
-
const { label, symbol } = legendItem || {};
|
|
176
|
+
const { label, symbol, line } = legendItem || {};
|
|
194
177
|
|
|
195
178
|
if (seriesType === 'line') {
|
|
196
|
-
|
|
197
|
-
|
|
179
|
+
// This is the case for the column plus line chart - the series type is
|
|
180
|
+
// line, but the chart type is column. In this case we show a simple
|
|
181
|
+
// line symbol in the legend, but we need to move the label to the right
|
|
182
|
+
// to account for the longer line symbol
|
|
183
|
+
if (chart.userOptions.chart.type !== 'line') {
|
|
184
|
+
label?.attr({
|
|
185
|
+
x: 30, // Adjust label position to account for longer line
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// This is the scenario for a line chart with markers disabled
|
|
190
|
+
// We have custom code in line-chart.js to update the last point to
|
|
191
|
+
// display as a symbol. This code checks if there is no symbol in the legend
|
|
192
|
+
// (which means it is a line chart with markers disabled)
|
|
193
|
+
// and if so, it updates the legend to display as a symbol rather than as a line
|
|
194
|
+
// We only to this for chart types that are explicitly line charts - i.e. not column with line
|
|
195
|
+
if (!symbol && label && label.element && chart.userOptions.chart.type === 'line') {
|
|
196
|
+
// Hide the line in the legend
|
|
197
|
+
if (line) {
|
|
198
|
+
line.hide();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Create a custom symbol for the legend using the line marker symbol options
|
|
202
|
+
const renderer = chart.renderer;
|
|
203
|
+
const bbox = label.element.getBBox();
|
|
204
|
+
const markerStyle = this.constants.lineMarkerStyles[index % this.constants.lineMarkerStyles.length];
|
|
205
|
+
|
|
206
|
+
const legendSymbol = renderer
|
|
207
|
+
.symbol(markerStyle.symbol, bbox.x - 30, bbox.y + 4, 12, markerStyle.radius, markerStyle.radius)
|
|
208
|
+
.attr({
|
|
209
|
+
fill: item.color,
|
|
210
|
+
stroke: item.color,
|
|
211
|
+
'stroke-width': 1,
|
|
212
|
+
width: 12,
|
|
213
|
+
height: 12,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
legendSymbol.add(label.parentGroup);
|
|
217
|
+
label?.attr({
|
|
218
|
+
x: 15, // Adjust label position to account for shorter space that the symbol takes up
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
} else if (seriesType === 'columnrange') {
|
|
222
|
+
symbol.attr({
|
|
223
|
+
width: 14,
|
|
224
|
+
height: 14,
|
|
225
|
+
y: 8,
|
|
198
226
|
});
|
|
199
227
|
} else {
|
|
200
228
|
if (!symbol) return;
|
|
201
|
-
//
|
|
229
|
+
// Update the symbol width and height
|
|
230
|
+
// For column, bar and other chart types
|
|
202
231
|
else {
|
|
203
232
|
symbol.attr({
|
|
204
233
|
width: 12,
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{% from "components/chart/_macro.njk" import onsChart %}
|
|
2
|
+
|
|
3
|
+
{{
|
|
4
|
+
onsChart({
|
|
5
|
+
"chartType": "column",
|
|
6
|
+
"description": "Public sector net debt excluding public sector banks, percentage of gross domestic product (GDP), UK, financial year ending (FYE) 1901 to October 2024",
|
|
7
|
+
"theme": "primary",
|
|
8
|
+
"title": "Figure 6: Net debt as a percentage of GDP remains at levels last seen in the early 1960s",
|
|
9
|
+
"subtitle": "Public sector net debt excluding public sector banks, percentage of gross domestic product (GDP), UK, financial year ending (FYE) 1901 to October 2024",
|
|
10
|
+
"id": "uuid",
|
|
11
|
+
"caption": "Source: Public sector finances from the Office for Budget Responsibility (OBR) and the Office for National Statistics",
|
|
12
|
+
"download": {
|
|
13
|
+
'title': 'Download Figure 1 data',
|
|
14
|
+
'itemsList': [
|
|
15
|
+
{
|
|
16
|
+
"text": "Excel spreadsheet (XLSX format, 18KB)",
|
|
17
|
+
"url": "#"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"text": "Simple text file (CSV format, 25KB)",
|
|
21
|
+
"url": "#"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"text": "Image (PNG format, 25KB)",
|
|
25
|
+
"url": "#"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"legend": false,
|
|
30
|
+
"series": [
|
|
31
|
+
{
|
|
32
|
+
"data": [
|
|
33
|
+
37.8, 41.0, 43.0, 42.9, 41.8, 39.8, 37.9, 38.2, 37.6, 36.7,
|
|
34
|
+
33.9, 31.8
|
|
35
|
+
],
|
|
36
|
+
"dataLabels": false,
|
|
37
|
+
"name": "Public sector net debt as a % of GDP (PSND)"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"xAxis": {
|
|
41
|
+
"categories": [
|
|
42
|
+
"Mar 1901", "Mar 1902", "Mar 1903", "Mar 1904", "Mar 1905", "Mar 1906", "Mar 1907", "Mar 1908", "Mar 1909", "Mar 1910",
|
|
43
|
+
"Mar 1911", "Mar 1912"
|
|
44
|
+
],
|
|
45
|
+
"title": "Years",
|
|
46
|
+
"type": "linear",
|
|
47
|
+
"tickIntervalMobile": 5
|
|
48
|
+
},
|
|
49
|
+
"yAxis": {
|
|
50
|
+
"title": "Percentage of GDP",
|
|
51
|
+
"customReferenceLineValue": 25
|
|
52
|
+
},
|
|
53
|
+
"percentageHeightDesktop": 35,
|
|
54
|
+
"percentageHeightMobile": 90
|
|
55
|
+
})
|
|
56
|
+
}}
|