Collapse/Expand Child Nodes - highcharts

In Highcharts Organization Chart, is there a way to hide the people below. So for instance, if you have the CEO and 5 people report to them. Can I add a button to the CEO node that will hide all children once clicked? Even deeper if the CTO reports to the CEO but the CTO has 9 people report to her, can I hide the CTO children and the CEO? Thanks so much.

I prepared an example of how to hide/show nodes under the CEO node on custom Highcharts button. By using this logic you should be able to create the rest of the wanted collapse buttons.
Demo: https://jsfiddle.net/BlackLabel/7orp61kx/
Render responsive button on render event:
events: {
render() {
let chart = this,
points = chart.series[0].points,
ceoPoint = points[1].toNode,
buttonX = ceoPoint.dataLabel.translateX,
buttonY = ceoPoint.dataLabel.translateY + chart.plotTop;
// check if button exist after window resize
if (chart.ceoButton) {
chart.ceoButton.destroy();
}
// create button
chart.ceoButton = chart.renderer.button('hide/show children', buttonX, buttonY, hideShow).add()
// translate button
chart.ceoButton.translate(buttonX - chart.ceoButton.getBBox().width, buttonY + chart.ceoButton.getBBox().height / 3)
}
}
hideShow function:
function hideShow() {
chart.series[0].points.forEach((p, i) => {
if (i > 1) {
if (p.state === "") {
p.graphic.hide();
p.toNode.graphic.hide();
p.toNode.dataLabel.hide();
p.state = 'hidden';
} else {
p.graphic.show();
p.toNode.graphic.show();
p.toNode.dataLabel.show();
p.state = ""
}
}
})
}
API: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#button
API: https://api.highcharts.com/highcharts/chart.events.render

Related

Qt/Qml - Press n hold the space bar - use your iphone space bar like a mouse

Is it possible to get such cursor control in QML TextArea?
for example, a video on this topic
https://www.youtube.com/watch?v=XRUCnZFv9Ro
Because Qt now encourages you to use QtQuick 2.x controls instead of QtQuick 1.x controls interactions need to be recreated in the Qt environment, and you can no longer rely on the OS to do this for you. Unfortunately, the user interaction you describe would take some effort to recreate.
To start, the following code only does the first part: intercepts the long press of a space. The second part had not been implemented, i.e. the handling of mouse drag:
import QtQuick
import QtQuick.Controls
Page {
property bool spaceDown: false
Item {
width: parent.width
height: frame.height
Frame {
id: frame
width: parent.width
opacity: holdArea.focus ? 0.2 : 1.0
TextEdit {
id: textEdit
width: parent.width
Keys.onPressed: {
if (event.key === Qt.Key_Space) {
if (spaceDown) {
holdArea.forceActiveFocus();
} else {
spaceDown = true;
}
}
}
}
}
Item {
id: holdArea
focus: true
Keys.onReleased: {
spaceDown = false;
textEdit.forceActiveFocus();
}
}
}
}
You can try the first part here

Is ScrollableTabRow lazy

If i create like 1000 Tabs within the ScrollableTabRow will it only compose the Tabs which are visible to the screen or`will compose everytime non-visible Tabs if something changes?
Like same as a LazyColumn composes only visible items.
I've written a minimal example in which i'm just "repeat"ing the same composable a lot of times - with no item{}-like DSL available like the lazy-components have.
#Composable
#Preview
fun MinimalTabExample() {
var selectedTabIndex by remember { mutableStateOf(0) }
ScrollableTabRow(selectedTabIndex = selectedTabIndex) {
repeat(60) { tabNumber ->
Tab(
selected = selectedTabIndex == tabNumber,
onClick = { selectedTabIndex = tabNumber },
text = { Text(text = "Tab #$tabNumber") }
)
}
}
}
Also, if you look into the ScrollableTabRow component you'll find that all the tabs are measured right at the beginning: (tabs are the compose-tabs created above)
val tabPlaceables = subcompose(TabSlots.Tabs, tabs)
.map { it.measure(tabConstraints) }
I guess this is implemented this way due to the height-calculation: "Make the height as high as the highest component"
tabPlaceables.forEach {
layoutWidth += it.width
layoutHeight = maxOf(layoutHeight, it.height)
}

How do I create a draggable plot line in Highcharts?

How do I create a draggable plotline in Highcharts? I couldn't find info about this. See please screenshot. You will see a green line on the screenshot. This plotline must be oriented on xAxis and draggable with max and min value on the axis Х. Can you help me? maybe some suggestion or link to official docs. Thank you in advanced.
screenshot
see pls also some short video
https://drive.google.com/open?id=1sHeIZU1S5M15yxbzKWQrTE44pdrUz7PW
You can simply render the rect element using Highcharts.SVGRenderer class, and then handle appropriate events, to change the line position on drag. Everything should be able to achieve on chart.events.load handler. Here is a sample code:
load() {
var chart = this,
lineWidth = 2,
draggablePlotLine = chart.renderer.rect(100, chart.plotTop, lineWidth, chart.plotHeight)
.attr({
fill: 'blue'
})
.add();
chart.container.onmousemove = function(e) {
if (draggablePlotLine.drag) {
let normalizedEvent = chart.pointer.normalize(e),
extremes = {
left: chart.plotLeft,
right: chart.plotLeft + chart.plotWidth
};
// Move line
if (
e.chartX >= extremes.left &&
e.chartX <= extremes.right
) {
draggablePlotLine.attr({
x: e.chartX
})
}
}
}
draggablePlotLine.element.onmousedown = function() {
draggablePlotLine.drag = true
}
draggablePlotLine.element.onmouseup = function() {
draggablePlotLine.drag = false
}
}
Live exampe: https://jsfiddle.net/Lnj7ac42/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer

jQuery ui-sortable open original place holder on drag outside of list

I have a sortable vertical single column list. What I need:
1) Open original placeholder where the element was on start when user drags an element outside of the list. I need it to prevent drop outside of list. Is it possible?
2) Is it possible to add or change tolerance option? I need to setup reordering (for vertical list) when top border of dragging element overlaps bottom border of list elements. I managed get this while dragginf upward but when you dragginf down sorting work on mouse overlap.
$('#sortable').sortable({
sort: function (event, ui) {
var list = $(this),
w = ui.helper.outerWidth(),
h = ui.helper.outerHeight();
list.children().each(function () {
if ($(this).hasClass('ui-sortable-helper') || $(this).hasClass('ui-sortable-placeholder')) {
return true;
}
var currElementHeight = $(this).outerHeight(),
overlap = $(this).position().top + currElementHeight - ui.position.top,
placeBefore = ui.position.top > $(this).position().top;
if (overlap > 0 && overlap < currElementHeight) {
if (placeBefore)
$('.ui-sortable-placeholder', list).insertBefore($(this));
else
$('.ui-sortable-placeholder', list).insertAfter($(this));
return false;
}
if ($(this).position().left + $(this).outerWidth() < ui.position.left) {
console.log('out');
//ui.item.parent().sortable('cancel');
}
});
},
});
Here is my experiments on jsfiddle

Make the legend disappear in Highcharts

I am using Highcharts and I am trying to make the legend to disappear and appear using a button, to save some screen real-estate.
I tried everything I could think of and all I managed to do is to make the SVG of the legend to hide and show using chart.legend.[group, nav, container].hide() but the white space which the legend takes never goes away. I even tried deleting the legend DOM element but the chart wouldn't resize (even calls to chart.reflow() don't help.
See here: http://jsfiddle.net/zbzzn/q83h5g4z/1/
Is there any way to make the legend disappear and reflow the chart so that the legend white space goes away?
Here's my sketch for a toggle method that sits directly on the Legend prototype. It avoids modifying the container width and height.
Highcharts.Legend.prototype.toggle = function () {
if (this.display) {
this.group.hide();
} else {
this.group.show();
}
this.display = !this.display;
this.chart.isDirtyBox = true;
this.chart.redraw();
};
Live demo at http://jsfiddle.net/highcharts/3Bh7b/76/
I managed to do a hack around it that works:
http://jsfiddle.net/q83h5g4z/4/
I really hope there is another way to do it without the hack.
if (!isVisible) {
originalLegendHeight = legend.legendHeight;
legend.options.maxHeight = -1; //0 doesn't work :( because someone did "if (maxHeight)" instead of "if (maxHeight === null)"
$('#container').height($('#container').height()-legend.legendHeight);
chart.redraw();
chart.reflow();
} else {
legend.options.maxHeight = null;
$('#container').height($('#container').height()+originalLegendHeight);
chart.redraw();
chart.reflow();
}
See this solution:
http://jsfiddle.net/3Bh7b/73/
var legend = chart.legend;
if(legend.display) {
legend.group.hide();
legend.display = false;
} else {
legend.group.show();
legend.display = true;
}
The final solution I reached is (where legendVisible determines the visibility of the legend) :
var legendElement = $(chart.container).find('.highcharts-legend');
if (legendElement.length > 0) {
if (chart.legend.options.enabled && legendVisible) {
legendElement.show();
chart.legend.options.maxHeight = chart.legend.options.originalMaxHeight || null;
chart.reflow();
} else {
legendElement.hide();
chart.legend.options.originalMaxHeight = chart.legend.options.maxHeight;
chart.legend.options.maxHeight = -1;
chart.reflow();
}
}

Resources