can someone explain why number of yaxis gridlines is less in exported svg rather than in the browser version? Is this happening because of margin update? if so, why it updates margin, but leaves old number of gridlines, shouldn't it be updated as well?
Here is my fiddle http://jsfiddle.net/sabira/r0zvouyp/
Thank you in advance!
Highcharts.chart('container', {
chart:{
events: {
load: function(){
const chart = this;
const {title, yAxis} = chart;
setRightDy(title);
const ticks = chart.yAxis[0].ticks;
let topTick = null;
for(let tick in ticks){
if(ticks[tick].isLast) {
topTick = tick;
}
}
const tickY = ticks[topTick].label.xy.y;
const extraMargin = chart.plotTop-tickY + 10;
const currentMargin = chart.title.alignOptions.margin;
chart.title.update({
margin: currentMargin+extraMargin
}, true, false, false)
}
}
},
title: {
align: 'left',
text: `
<span class='titleText' style="font-weight: 500; font-size: 12.6px; font-family: Retina; fill:black"> Lorem ipsum dolor sit amet </span><br>
<span class='dekText' style="font-size: 8.4px; fill: black; font-weight: 300; font-family: Retina"> Integer quis pharetra tellus. Cras tincidunt libero id dignissim convallis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</span><br>
<span class='subdekText--strong' style="font-weight: 500; font-size: 8.4px; font-family: Retina; fill:black">Sed aliquam ligula in pretium lobortis.</span>
<span class='dekText' style="font-size: 8.4px; fill: black; font-weight: 300; font-family: Retina"> Integer quis pharetra tellus. Cras tincidunt libero id dignissim convallis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</span><br>
<span class='subdekText--strong' style="font-weight: 500; font-size: 8.4px; font-family: Retina; fill:black">Sed aliquam ligula in pretium lobortis.</span>
`,
widthAdjust: -40,
margin: 20,
},
exporting: {
scale: 1
},
yAxis: {
labels: {
align: 'left',
x: 0,
y: -4
}
},
series: [{
data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
}],
});
According to comments - your case is more complicated, but I think that a good solution is do also a yAxis.tickAmount update with a current ticks amount to do not calculate them again while the chart is initializing for exporting. See:
Demo: https://jsfiddle.net/BlackLabel/wju68av5/
chart.update({
title: {
margin: currentMargin + extraMargin
},
yAxis: {
tickAmount: chart.yAxis[0].tickPositions.length
}
}, true, false, false)
The problem which you are struggling to is that you set the new margin after the initial load, which changes and animate the chart. However, the export server renders a new chart with a options which you used to set but without loading the load callback, because there is no delay time to do it.
Why don't you just set the calculated margin as a fixed value in the title.margin object and set the wanted amount of ticks to get it? The visual output is the same.
Demo: https://jsfiddle.net/BlackLabel/owr6f7z2/
yAxis: {
labels: {
align: 'left',
x: 0,
y: -4
},
tickAmount: 7
},
API: https://api.highcharts.com/highcharts/yAxis.tickAmount
If this answer wouldn't fit your requirements please describe more precisely what do you want to achieve.
Related
I have a horizontal bar chart with negative and positive values,
I noticed that gridlines have a slight offset to the left (maybe they get rounded?). Here is an image that illustrates my problem:
I tried to reproduce it in fiddle, but got slightly different result (please export png to see the image). It's hard to notice but negative bars don't start from zero.
So I am curios to know what is the root cause of the problem and potential fix you may suggest.
Thanks in advance!
Highcharts.chart('container', {
chart: {
type: 'bar',
styledMode: true,
events: {
load: function(){
const chart = this;
const gridLines = chart.yAxis[0].gridGroup.element.querySelectorAll('path');
console.log(gridLines);
const yTicks = chart.yAxis[0].ticks;
for(let tick of Object.keys(yTicks)){
if(yTicks[tick].pos === 0) {
const zeroGridLine = yTicks[tick].gridLine.element;
zeroGridLine.classList.replace('highcharts-grid-line','zero-line');
if(chart.seriesGroup) chart.seriesGroup.element.appendChild(zeroGridLine)
break;
}
}
}
}
},
title: {
text: 'title'
},
xAxis: {
categories: ['Medical care',
'Shelter',
'Personal services',
'Education',
'Furnishings',
'Communication',
'Recreation',
'Fuels and utilities',
'Apparel',
'Transportation',],
lineWidth: 1,
labels: {
align: 'left',
reserveSpace: true,
step: 1,
x:-5,
/* max: 9.5,
min: -0.5, */
style: {
whiteSpace: 'wrap',
textOverflow: 'visible'
}
}
},
yAxis: {
tickWidth: 1
},
series: [{
name: 'April 2020',
data: [
4.81, 2.62, 2.53, 2.15, 1.31, 1.12, 0.94, -0.35, -3, -8]
}, {
name: 'Jan 2020',
data: [4.48, 3.32, 2.11, 2.17, 0.66, 0.93, 1.41, 0.57, -1.26, 2.87]
}]
})
#import 'https://code.highcharts.com/css/highcharts.css';
#container {
min-width: 300px;
max-width: 300px;
height: 300px;
margin: 1em auto;
}
.highcharts-xaxis-labels {
font-size: 15px;
}
.zero-line {
stroke: black;
stroke-width: 1;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="height: 400px"></div>
I think that it is a bug. I reported it on the Highcharts Github issue channel where you can follow this thread or add your own opinion about this behaviour. The core developers will respond you.
https://github.com/highcharts/highcharts/issues/14302
I can't seem to override the defaults to vertically align the checkbox relative to the checkbox label. Searched for a while but nothing has worked. See example image:
Should be like:
Have tried the following:
.mat-checkbox-inner-container {
margin: none;
}
HTML:
<label><b>Home Type</b></label>
<mat-checkbox>Entire place<br><small class="text-muted">Have a place to yourself</small></mat-checkbox>
<mat-checkbox>Private room<br><small class="text-muted">Have your own room and share some common spaces</small></mat-checkbox>
<mat-checkbox>Shared room<br><small class="text-muted">Stay in a shared space, like a common room</small></mat-checkbox>
Similar to Craig's answer but as a descendant of .mat-checkbox.mat-accent to spare the need of using "!important"
.mat-checkbox.mat-accent .mat-checkbox-inner-container {
margin: 2px 8px auto 0;
}
or using sass/less
.mat-checkbox.mat-accent {
.mat-checkbox-inner-container {
margin: 2px 8px auto 0;
}
}
Just run into the same problem. I used the following to solve it (unfortunately needs the dreaded !important):
.mat-checkbox-inner-container {
margin: 2px 8px auto 0 !important;
}
I found I had to adjust the top margin (2px in this case) to get the layout beside the label to look correct.
I was able to achieve this (I'm using Angular/Material 7.x) by resetting the margins the checkbox container uses.
Note that I have had to apply an additional translateY to account for the box's border-width, and reset the wrap on the label so the text doesn't try to stay on one line.
your.component.scss
:host {
::ng-deep {
.mat-checkbox-inner-container {
margin-top: initial;
margin-bottom: initial;
transform: translateY(2px); // value of checkbox border-width
}
.mat-checkbox-label {
white-space: normal; // wrap label text
}
}
}
StackBlitz Fiddle
I know this is old, but below worked for me – I honestly didn't even know auto worked with vertical alignment, but I guess it does 🤷🏽♂️:
.mat-checkbox-inner-container {
margin-top: 0;
}
<div>
<h1>LABEL CHECKBOX</h1>
<mat-checkbox class="mat-checkbox-layout"><strong>FINE</strong>Lorem ipsum dolor sit amet consectetur adipisicingelit. Optio vitae molestiae nemo magni odio voluptate corporis veniam sapiente earum fugiat rem,maiores et placeat qui iure, nobis ipsam sintenim.</mat-checkbox>
<mat-checkbox class="mat-checkbox-layout"><strong>OK</strong>Lorem ipsum dolor sit amet consectetur adipisicing elit.Optio vitae molestiae nemo magni odio voluptate corporis veniam sapiente earum fugiat rem, maiores et placeat qui iure, nobis ipsam sintenim.</mat-checkbox>
</div>
And the CSS is this (I create css class identically with angular css class)
.mat-checkbox-layout {
text-align: justify;
}
::ng-deep .mat-checkbox-layout .mat-checkbox-layout {
white-space: normal !important;
}
:host {
::ng-deep {
.mat-checkbox-layout {
align-items: end!important;
}
.mat-checkbox-label {
white-space: normal; // wrap label text
}
}
}
There is a fast solution which is not related to ng-material
you can put your "mat-checkbox" into "li" element and align your "ul" by setting the number of columns like this:
<ul style="columns:2">
<li>
<mat-checkbox>Entire place<br><small class="text-muted">Have a place to yourself</small></mat-checkbox>
</li>
<li>
<mat-checkbox>Private room<br><small class="text-muted">Have your own room and share some common spaces</small></mat-checkbox>
</li>
<li>
<mat-checkbox>Shared room<br><small class="text-muted">Stay in a shared space, like a common room</small></mat-checkbox>
</li>
</ul>
I'm trying to export my highchart to a table below it. In their documentation about Highchart Table, I only found this with this example
I'm trying to style the table with colored thead, but there's no thead tag in Highcharts' table. This doesn't work too
// draw category labels
chart.xAxis[0].categories.forEach(function (name, i) {
renderer.text(
name,
cellLeft + cellPadding,
tableTop + (i + 2) * rowHeight - cellPadding
)
.css({
fontWeight: 'bold',
backgroundColor: '#aaa'
})
.add();
});
Things I'm trying to do:
1. Color the thead
2. Append the average temperature below the chart
3. Erase the empty border stroke above the Month column
4. Make the table responsive
I can't seem to find any Highchart table documentation. Any help is welcomed. Thank you
This css worked for me and it is responsive!
I got the css from this demo.
I just cut and paste it into my css file and DONE.
.highcharts-data-table table {
border-collapse: collapse;
border-spacing: 0;
background: white;
min-width: 100%;
margin-top: 10px;
font-family: sans-serif;
font-size: 0.9em;
}
.highcharts-data-table td, .highcharts-data-table th, .highcharts-data-table caption {
border: 1px solid silver;
padding: 0.5em;
}
.highcharts-data-table tr:nth-child(even), .highcharts-data-table thead tr {
background: #f8f8f8;
}
.highcharts-data-table tr:hover {
background: #eff;
}
.highcharts-data-table caption {
border-bottom: none;
font-size: 1.1em;
font-weight: bold;
}
I think it would be easier for you to use the table generated by the export-data.js module.
It can be called like this, if you want to always show it:
chart: {
events: {
load: function() {
this.viewData()
}
},
...
}
Then you can style that table like a normal html table, e.g:
.highcharts-data-table thead {
background-color: #aaa;
}
To find the average you can calculate that based on the values on the html table and call it after the viewData function has been called, see example.
function getAverages(rowVals) {
let averages = ''
rowVals.forEach(function(arr, i) {
if (i != 0)
averages += '<td>' + (arr.reduce(function(a, b) {
return a + b;
}) / arr.length).toFixed(1) + '</td>'
});
return averages
}
function addHtmlTableAverage() {
var table = $('.highcharts-data-table table')[0],
avgVal, sumVal = 0,
rowCount = table.rows.length - 1,
rowVals = [
[]
]; // minus the header
for (var i = 1; i < table.rows.length; i++) {
for (let j = 1; j < table.rows[i].cells.length; j++) {
if (rowVals[j]) {
rowVals[j].push(parseFloat(table.rows[i].cells[j].innerHTML))
} else {
rowVals.push([parseFloat(table.rows[i].cells[j].innerHTML)])
}
}
}
$('.highcharts-data-table table > tbody:last')
.append('<tr class="averages"><td><b>Avg</b></td>' +
getAverages(rowVals) +
"</tr>")
}
/**
* Create the chart
*/
window.chart = Highcharts.chart('container', {
chart: {
events: {
load: function() {
this.viewData()
addHtmlTableAverage()
}
},
borderWidth: 2,
width: 600,
height: 300
},
title: {
text: 'Average monthly temperatures'
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: {
title: {
text: 'Temperature (°C)'
}
},
series: [{
name: 'Tokyo',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
}, {
name: 'New York',
data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
}, {
name: 'Berlin',
data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
}, {
name: 'London',
data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
}]
});
#container {
margin-top: 20px;
}
.highcharts-data-table thead {
background-color: #aaa;
}
.averages td {
background-color: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<div id="container"></div>
Working example: http://jsfiddle.net/ewolden/6gh05usq/2/
Every item you want to add to the table you need to generate. For example thead background: http://jsfiddle.net/BlackLabel/0behnswa/
Snippet:
// Apply thead background:
renderer.rect(
cellLeft,
tableTop + cellPadding,
colWidth,
rowHeight
)
.attr({
fill: 'rgba(150, 150, 150, 0.5)'
})
.add()
In short, you need to play around with code to modify it the way you wan to.
For example, remove parts of code that are responsible to generate empty cell: http://jsfiddle.net/BlackLabel/0behnswa/2/
The big part is "responsive" table. This is SVG, that means you need to write all responsive options. On top, you can find options to configure:
// user options
var tableTop = 310,
colWidth = 100,
tableLeft = 20,
rowHeight = 20,
cellPadding = 2.5,
...
Those are fixed numbers, you need to calculate them.
I have a highchart in three languages with data filled from a database. Some of the translated titles will break and fill two lines. Without any precaution this will overflow the subtitles:
title: {
text: 'The quick brown fox jumps over the lazy dog and even more',
style: {
width: '320px'
}
},
subtitle: {
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr'
},
See this sample: http://jsfiddle.net/puhtu/
Is there a way to dynamically move the subtitles if the main title breaks in two lines?
It looks like a bug so I've reported it to our devs https://github.com/highslide-software/highcharts.com/issues/1704
Although a while ago, the following fixed it for me since this is still an issue:
title: {
text: "Hello very strange world where people tend to make long chart titles",
style: {
fontSize: '1.9vmin',
fontWeight: 'bold',
color: '#1381bc',
lineHeight: '15em' //This line did the trick
},
align: 'left',
x: 30,
y: 10
},
For the problem I'm trying to solve, I have a table with unique content for each row. The rows are allowed to be reordered via a handle, and the content of each row is not always of uniform height. Sometimes large amounts of text and / or images appear within a row.
There can also be multiple tables with rows that can be reordered, so I'm using the containment property to prevent dragging into other zones and other problematic issues that occur when dragging outside the desired area.
The problem is when I attempt to drag a "tall" row to the top or bottom of the order when the top and bottom are "short" by comparison. Essentially I am not allowed to drag tall rows to the these positions. I have searched for a solution and have come up short. Any help would be appreciated.
Working example here: http://jsfiddle.net/jeffvoigt/XyPzf/
Neither of the two middle rows can be dragged to the top or bottom of the list.
HTML:
<div class="container">
<table id="sortable">
<tr class="odd">
<td><p>[=]</p></td>
<td>Single Line of Text</td>
</tr>
<tr class="even">
<td><p>[=]</p></td>
<td>Aenean porta, tellus quis auctor elementum, risus ante ornare augue, eu elementum nunc libero ut nisi. Pellentesque sed vestibulum tellus. Proin convallis enim eget felis iaculis viverra vestibulum lorem semper. Aliquam imperdiet viverra lorem, ut dignissim felis laoreet vel. Suspendisse fermentum neque eu est vestibulum bibendum. Maecenas dignissim egestas tempor. Ut tincidunt metus sed felis ornare nec sollicitudin risus gravida. Duis vitae mauris quis risus ultricies malesuada. Nulla facilisi. Phasellus fringilla, arcu eget congue sollicitudin, lorem elit ullamcorper ante, non fermentum orci mauris at tellus. Maecenas suscipit sodales molestie. Mauris luctus porta dui non volutpat.</td>
</tr>
<tr class="odd">
<td><p>[=]</p></td>
<td><img src="http://www.google.com/intl/en_ALL/images/logos/images_logo_lg.gif" /></td>
</tr>
<tr class="even">
<td><p>[=]</p></td>
<td>Single Line of Text</td>
</tr>
</table>
</div>
Javascript:
$( "#sortable tbody" ).sortable({
axis: "y",
containment: ".container",
cursor: "move",
handle: "p"
});
I faced the same issue. This is the quick solution:
$('.collections').sortable({
handle: 'h3',
axis: 'y',
containment: 'parent',
items: '.collection',
cursor: 'move',
tolerance: 'pointer',
scroll: true,
beforeStop: function(event, ui) {
var lastElemTop = $('.collections .collection:last-child').position().top;
var currElemTop = ui.position.top;
var currElemHeight = ui.item.height();
if (currElemTop + currElemHeight * 2 > lastElemTop) {
$('.collections .collection:last-child').insertBefore(ui.item);
}
}
});
The problem is the placement of your handle determines the Y position of the sort in relation to the handle it is on top of. So, to demonstrate, go to jsFiddle and add a valign=top to your big text area. The handle moves to the top of the sortable element, and when you drag it to the top where the short line of text is it will snap into place, but you cannot get it to sort to the bottom. However, if you update the fiddle to be valign=bottom, you may snap it to the bottom but not the top.
Solutions would be to either make your entire content area a sortable handle or perhaps move your handles out to the left of the content (making that the 'sortable' area only) and drag only the handles (not the content), then allow the the content area to update upon a new sort.
Basically, it needs to be some how re-envisioned or designed to function properly.
I encountered this very same problem. It seems like this only happens when there is no content or spacing beneath the jQuery Sortable list.
Just adding some spacing (e.g. <div id="end-of-page-spacer" style="height: 500px;"></div>) allowed me to drag large rows beneath smaller rows situated at the bottom of the list.