Adding multiple annotation bodies at the same time
Apeli opened this issue · comments
Hi, I'm trying to make a list of preselected values that would add a comment + colorcode to the annotation at the same time. I took the ColorSelectorWidget from https://recogito.github.io/guides/extending-the-editor/ as the base. I got to the point where I have the buttons, but when clicking on one, I can only set one body per click. So calling addTag the actual annotation only has 1 body, which ever is called last.
I tried like this:
var addTag = function(evt) {
args.onAppendBody({
type: 'TextualBody',
purpose: 'highlighting',
value: evt.target.dataset.color,
});
args.onAppendBody({
type: 'TextualBody',
purpose: 'commenting',
value: evt.target.dataset.tag,
});
...
There the annotation only has the 'commenting' -body. Is there a way to set multiple bodies at the same time?
Good point - yes, interestingly no-one raised that as a requirement so far. It's not currently possible to add multiple bodies in one go. The onAppendBody method is async. Therefore, the second call essentially overwrites the first one.
If this is urgent: an ugly hack would be to delay the second call by a few milliseconds.
setTimeout(() => args.appendBody({...}), 1); // 1 might be sufficient to put it at the end of the queue
But for a clean solution, I'd need to extend the API with .onAppend/Update/UpsertBodies()
methods. (Or simply make the current methods accept a single body or an array.)
Just moving this issue to the core module, which contains the code for the editor.
Thanks for a quick answer - but the setTimeout hack didn't work, 1/100/1000 ms delay made no difference. Any other hacks that come to mind :) ?
Yikes, of course... your widget is Vanilla Javascript, right? Not React... I totally forgot that in this case, the whole widget function will be destroyed an recreated. I.e. my suggested workaround isn't a workaround after all...
Hm, no I think there's no way to hack your way around this. At least not without touching the code of the Editor itself. Luckily, though, the code change required inside the editor si quite minimal. I'll see if I can get that done over the next day(s).
Yeah, I'm doing it in a vanilla js widget (which is used in a Vue component :))
The latest state on the main branch now has support for both this requirement (adding multiple bodies in one go), and saving immediately after an annotation update (#66). The key changes are:
.onAppendBody
and.onRemoveBody
now support a single body as well as an array of bodies as argument- Callback functions now have an extra
saveImmediately
argument (default false). Set it to true to save & close the editor immediately after performing the update.
For example, if you want to add two bodies and close immediately:
args.onAppendBody([ body1, body2 ], true);
P.S.: this still needs some testing, because it required a bit of a foundational change to the editor implementation. But otherwise it will go live with the next releases of Annotorious and RecogitoJS.
I changed the API to make this a bit cleaner + more flexible.
- All the normal modification methods (
onAppendBody
,onRemoveBody
,onUpdateBody
,onUpsertBody
) take only a single body as argument (and, optionally, asaveImmediately
flag to close the editor) - There's a new method called
onBatchModify(changes, saveImmedately)
which takes a list of changes as argument.
Example:
const changes = [
{ action: 'append', body: bodyToAppend },
{ action: 'update', previous: prevBody, updated: updatedBody }
{ action: 'remove', body: bodyToRemove },
// Normal upsert, previous is optional
{ action: 'upsert', previous: prevBody, updated: updatedBody }
// Auto-upsert based on purpose
{ action: 'upsert', body: bodyToUpser }
]
This keeps the original API as it was, plus provides a mechanism to apply any combination of modifications, with or without closing the editor immediately afterwards.