Introduce root order property for multi-root editor
📝 Provide a description of the improvement
In the multi-root editor, there's no root ordering (by default, if you don't write it yourself). Right now, when a root is added, it is added at the end of roots collection. If a feature would want to traverse all the model roots to obtain some data (e.g. headers or full document data), then there's no order.
However, root ordering (and re-ordering) should be a pretty common use case. It is also needed for undo: if you removed a root, when you undo, it should be re-inserted at a correct place, not back again at the end of roots collection.
The property would be used by other plugins that might need to know what is the order of the roots, e.g. document outline, export to PDF, or a feature that would take care of correct placement of DOM editable elements in some container.
However, features should not know about the editor type (should not try to guess it). It should be implemented in a transparent way, if possible.
The most common API point that features use is model.document.getRootNames() or (.getRoots() if we introduce that). It would be great if these come sorted. But that would mean that the mechanism would need to be prepared in the engine.
We could possibly use root attributes here. Most editors will never need it and will never use it. The integrators will not need to save this value. If not set directly (loaded) it would be set automatically. We could set it only if there are two or more roots different than $graveyard. So, there would be effectively no difference for 99% users.
This property by itself will not have any impact on displaying the editable areas. There will be no feature to change the order either. Multi-root editor integrator will need to provide these. Eventually, at some point, we might provide some order feature for multi-roots but the UI will be very different from application to application, so I am not convinced this will be useful.
The roots are created by the writer:
model.Writer#addRoot( rootName: string, elementName = '$root' ): RootElement
We could add a third parameter here index?: number. If not set, the new root will be added at the end. But that's optional. We will be fine with adding the root to the end and requiring the integrator to set root property order accordingly.
And now, when it comes to the order property itself, it's not trivial if you want to provide a way to re-order roots. Ideally, you would want to change order of just one root, not all of them. The simplest idea is to use big numbers for order value, e.g. each root will get order higher by 100000. This gives you some space if you want to put a new root between two order roots. But not matter how you fine-tune this, you will always get some limitations.
An alternative solution would be a meta-root that would hold abstract elements that represent roots. It would be a tree, it could also represent that some roots are children (sub-roots) of other roots. This way, properties would not be needed but instead you would need to store this meta-structure. Which could be inconvenient too. But it's best for real-time collaboration too.
A mix of these would be to use meta-root internally but return order or index values. The problem with this is that you will have to update all entries (documents) in your database if you add a root at the beginning.
Maybe there's some other solution.
There has been no activity on this issue for the past year. We've marked it as stale and will close it in 30 days. We understand it may still be relevant, so if you're interested in the solution, leave a comment or reaction under this issue.
We've closed your issue due to inactivity. We understand that the issue may still be relevant. If so, feel free to open a new one (and link this issue to it).