Skip to content
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

Controlling selection behaviour #153

Open
Aierie opened this issue Oct 3, 2024 · 5 comments
Open

Controlling selection behaviour #153

Aierie opened this issue Oct 3, 2024 · 5 comments

Comments

@Aierie
Copy link

Aierie commented Oct 3, 2024

Hello! Wondering about controlling selection behaviour from userland.

I am making an app that has different behaviours on selection when different keys are pressed, and needs to be able to conditionally select a group of related annotations when one of them are clicked, and toggle selection state of a single annotation without interfering with other annotations. Initially, looking at the interface of clickAnnotation event here, I thought I would be able to retrieve whether modifier keys are pressed from the original event. However, it seems like clickAnnotation is not implemented for @recogito/text-annotator.

I then tried listening for DOM click events and checking whether they were on a range of an annotation:

document.querySelector('#annotator-target-example-6').addEventListener('click',(e) => {
	let range,textNode,offset;
	if (document.caretPositionFromPoint) {
		range = document.caretPositionFromPoint(
			e.clientX,
			e.clientY,
		);
		textNode = range.offsetNode;
		offset = range.offset;
	} else if (document.caretRangeFromPoint) {
		// Use WebKit-proprietary fallback method
		range = document.caretRangeFromPoint(e.clientX, e.clientY);
		textNode = range.startContainer;
		offset = range.startOffset;
	} else {
		throw new Error('document.caretPositionFromPoint and document.caretRangeFromPoint are not supported');
	}
	let annotations = annotator.getAnnotations();
	let annotationId = annotations.map((v) => [v.id, v.target.selector[0].range]).find(([k, r]) => { return r.isPointInRange(textNode, offset); })[0];
	if (!annotationId) return;
	if (e.altKey) {
		let selectedIds = new Set(annotator.getSelected().map((a) => a.id));
		if (selectedIds.has(annotationId)) {
			selectedIds.delete(annotationId);
		} else {
			selectedIds.add(annotationId);
		}
		annotator.setSelected(
			[...selectedIds]
		)
	} else {
		annotator.setSelected(
			[
				annotationId
			]
		)
	}
});

But it seems like internally, even with userSelectAction set to UserSelectAction.NONE, TextAnnotatorState is calling userSelect here:

selection.userSelect(hovered.id, evt);

Which in turn will either set the selected annotations to an empty array, or to a single one.

Is there any way around this? Would I need to maintain selection state in my own app or perhaps in an annotation's properties?

@Aierie
Copy link
Author

Aierie commented Oct 3, 2024

Perhaps I am using selection state in a way that doesn't quite match its intended use...

@rsimon
Copy link
Member

rsimon commented Oct 3, 2024

Hi,

it's all still a bit work in progress in here ;-) I'll take a look when I get the chance. But I think all you might be missing is the clickAnnotation event which, indeed, isn't implemented in the text annotator library yet (only in Annotorious). The UserSelectionAction.NONE setting might still have issues, too, I believe.

@Aierie
Copy link
Author

Aierie commented Oct 4, 2024

Thanks! Are any of these things that I could help with?

If you're open to me helping with these things, it would be good to understand how I could address the main blocking one (UserSelectAction.NONE) - what would be the best way to address this with Annotorious' architecture?

@rsimon
Copy link
Member

rsimon commented Oct 4, 2024

Definitely. The UserSelectionAction.NONE one is a bit tricky. But not really rocket science. Basically, it should be a few well-placed if conditions in the SelectionHandler.

You'd also have to hand the userSelectAction setting into the SelectionHandler in the first place, allow changes to the setting via a .set method etc. Therefore, it's not exactly trivial either. But at least it should be (mostly) constrained to that one source file. Feel free to give it a try and send a PR!

@oleksandr-danylchenko
Copy link
Contributor

You'd also have to hand the userSelectAction setting into the SelectionHandler in the first place, allow changes to the setting via a .set method etc.

That's already been handled by the parent's annotorious library ✅
Here are the PRs where I made the userSelectAction interactive and accessible from outside:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants