-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Layout service supports configuring box order #3812
Conversation
src/core/core.layoutService.js
Outdated
/** | ||
* Register a box to a chartInstance. | ||
* A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title. | ||
* @method Chart.layoutService.addBox |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did this documentation method based on http://stackoverflow.com/a/6460748 because it generated less docs than doing something to define an interface. Once we have gulp docs
in, I can test this and see what it generates
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, that works well for nested arguments, but I think here it's really an interface and it's quite weird to have these left, top, right, bottom
properties part of the function inputs. This method expects an object that implements the IBox
(or ILayoutBox
or ILayoutItem
) interface, as we have for IPlugin
, IPlatform
or IEvent
. Also more convenient if we need to refer to that interface from somewhere in the doc.
Actually, it doesn't require so much more doc if you define the interface as I did for IEvent
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I will update to follow the same way as IEvent
src/core/core.layoutService.js
Outdated
|
||
// Ensure that all boxes have an order | ||
if (!box.order) { | ||
box.order = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about this. sort
is not stable, so I don't think this guarantees the order of boxes. It might be better so simply set box.order = chartInstance.boxes.length
so that it's more likely to be a unique value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default order
should be 0, because boxes can be registered from anywhere, so it would be impossible to really control the box order:
addBox(chart, {}); // foo (index 0)
addBox(chart, {order: 1}); // bar (index 1)
addBox(chart, {}); // xyz (index 2)
Effective order is:
- case default to 0:
[foo, xyz, bar]
(expected) - case auto-increment:
[foo, bar, xyz]
Instead, we could use the box index as second sort criteria to obtain a stable sort:
function sort(array, reverse) {
return array.map(function(v, i) {
v._tmp_index_ = i;
})
.sort(function (a, b) {
var v0 = reverse? b : a;
var v1 = reverse? a : b;
return v0.order === v1.order?
v0._tmp_index_ - v1._tmp_index_ :
v0.order - v1.order;
})
.map(function(v) {
delete v._tmp_index_;
});
}
update: function() {
sort(leftBoxes, false);
sort(rightBoxes, true);
sort(topBoxes, false);
sort(bottomBoxes, true);
}
Not super efficient, but I don't think there will be so much boxes to sort!
src/core/core.layoutService.js
Outdated
@@ -79,6 +113,14 @@ module.exports = function(Chart) { | |||
return (a.options.fullWidth ? 1 : 0) - (b.options.fullWidth ? 1 : 0); | |||
}); | |||
|
|||
// Ensure that boxes are sorted by order. Higher order means further away from the chart | |||
leftBoxes.sort(function(a, b) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we apply this to top and bottom boxes as well? If so, we need to change the sorts
just above here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, maybe options.fullWidth
should not be used anymore to control the box order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's probably a good idea. I will make that change
src/core/core.layoutService.js
Outdated
|
||
// Ensure that all boxes have an order | ||
if (!box.order) { | ||
box.order = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default order
should be 0, because boxes can be registered from anywhere, so it would be impossible to really control the box order:
addBox(chart, {}); // foo (index 0)
addBox(chart, {order: 1}); // bar (index 1)
addBox(chart, {}); // xyz (index 2)
Effective order is:
- case default to 0:
[foo, xyz, bar]
(expected) - case auto-increment:
[foo, bar, xyz]
Instead, we could use the box index as second sort criteria to obtain a stable sort:
function sort(array, reverse) {
return array.map(function(v, i) {
v._tmp_index_ = i;
})
.sort(function (a, b) {
var v0 = reverse? b : a;
var v1 = reverse? a : b;
return v0.order === v1.order?
v0._tmp_index_ - v1._tmp_index_ :
v0.order - v1.order;
})
.map(function(v) {
delete v._tmp_index_;
});
}
update: function() {
sort(leftBoxes, false);
sort(rightBoxes, true);
sort(topBoxes, false);
sort(bottomBoxes, true);
}
Not super efficient, but I don't think there will be so much boxes to sort!
src/core/core.layoutService.js
Outdated
/** | ||
* Register a box to a chartInstance. | ||
* A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title. | ||
* @method Chart.layoutService.addBox |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, that works well for nested arguments, but I think here it's really an interface and it's quite weird to have these left, top, right, bottom
properties part of the function inputs. This method expects an object that implements the IBox
(or ILayoutBox
or ILayoutItem
) interface, as we have for IPlugin
, IPlatform
or IEvent
. Also more convenient if we need to refer to that interface from somewhere in the doc.
Actually, it doesn't require so much more doc if you define the interface as I did for IEvent
.
src/core/core.layoutService.js
Outdated
/** | ||
* Register a box to a chartInstance. | ||
* A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title. | ||
* @method Chart.layoutService.addBox |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't need to define @method since it's part of the Chart.layoutService
object.
src/core/core.layoutService.js
Outdated
* @param {Core.Controller} chartInstance the chart to use | ||
* @param {Object} box the box to add | ||
* @param {Number} box.order the order of the boxes. Higher numbers are further away from the chart area | ||
* @param box.options Options for configuring the box |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are there some options under box.options
and some others directly under box
?
src/core/core.layoutService.js
Outdated
chartInstance.boxes.push(box); | ||
}, | ||
|
||
/** | ||
* Remove a box from a chart | ||
* @param {Core.Controller} chartInstance the chart to remove the box from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be {Chart.Controller}
to bind that parameter to the controller doc.
src/core/core.layoutService.js
Outdated
@@ -79,6 +113,14 @@ module.exports = function(Chart) { | |||
return (a.options.fullWidth ? 1 : 0) - (b.options.fullWidth ? 1 : 0); | |||
}); | |||
|
|||
// Ensure that boxes are sorted by order. Higher order means further away from the chart | |||
leftBoxes.sort(function(a, b) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, maybe options.fullWidth
should not be used anymore to control the box order.
Can we rename |
I will change |
a1f94a1
to
6a012d6
Compare
@simonbrunel when you get a chance, can you review this after the changes? |
Should we add unit tests? |
@simonbrunel I'll add some tests to ensure that the sorting and stuff works as expected. |
…e ordered on left and right edges
Resolves #3388
The layout system now supports an
order
property which is used to align left and right boxes. A higher value is further away from the chart. This should not change the axis positions, and I did not observe any differences. It may be prudent to wait until v2.6 to include this.After Fix