Start work to also enable highlighting for list items
This commit is contained in:
parent
56b973f02e
commit
4464b56cbb
|
|
@ -32,9 +32,17 @@ const isInsideViewport = (position: number) => {
|
||||||
return position >= TOP_TRESHOLD && position <= BOTTOM_TRESHOLD;
|
return position >= TOP_TRESHOLD && position <= BOTTOM_TRESHOLD;
|
||||||
};
|
};
|
||||||
|
|
||||||
const findClosestAncestorWithTag = (node: Node, tag: string): HTMLElement | null => {
|
const findClosestAncestorWithTag = (node: Node, tags: string | string[]): HTMLElement | null => {
|
||||||
|
let tagList = tags;
|
||||||
|
if (!Array.isArray(tagList)) {
|
||||||
|
tagList = [tagList];
|
||||||
|
}
|
||||||
let currentNode: Node | null = node;
|
let currentNode: Node | null = node;
|
||||||
while (currentNode && currentNode.nodeName.toLowerCase() !== tag && currentNode.nodeName.toLowerCase() !== 'body') {
|
while (
|
||||||
|
currentNode &&
|
||||||
|
!tagList.includes(currentNode.nodeName.toLowerCase()) &&
|
||||||
|
currentNode.nodeName.toLowerCase() !== 'body'
|
||||||
|
) {
|
||||||
currentNode = currentNode.parentNode;
|
currentNode = currentNode.parentNode;
|
||||||
}
|
}
|
||||||
if (currentNode) {
|
if (currentNode) {
|
||||||
|
|
@ -93,34 +101,31 @@ export const getSelectionHandler =
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
if (isInsideViewport(rect.top) || isInsideViewport(rect.bottom)) {
|
if (isInsideViewport(rect.top) || isInsideViewport(rect.bottom)) {
|
||||||
// the listener only does something if the `el` is visible in the viewport, to save resources
|
// the listener only does something if the `el` is visible in the viewport, to save resources
|
||||||
|
|
||||||
// now we check if the selection is inside our container
|
// now we check if the selection is inside our container
|
||||||
|
|
||||||
const selection = rangy.getSelection();
|
const selection = rangy.getSelection();
|
||||||
if (selection.rangeCount && !selection.isCollapsed) {
|
if (selection.rangeCount && !selection.isCollapsed) {
|
||||||
|
// ⬆️ sat least one selection exists and is not of length 0
|
||||||
const range = selection.getRangeAt(0);
|
const range = selection.getRangeAt(0);
|
||||||
if (range.intersectsNode(el)) {
|
if (range.intersectsNode(el)) {
|
||||||
// the selection is inside our container, so we can do something with it
|
// the selection is inside our container, so we can do something with it
|
||||||
const { startContainer, endContainer } = range;
|
const { startContainer, endContainer } = range;
|
||||||
const paragraph = findClosestAncestorWithTag(startContainer, 'p');
|
const startAncestor = findClosestAncestorWithTag(startContainer, ['p', 'li']);
|
||||||
const endAncestor = findClosestAncestorWithTag(endContainer, 'p');
|
// const endAncestor = findClosestAncestorWithTag(endContainer, 'p');
|
||||||
|
if (!startAncestor) {
|
||||||
if (!paragraph) {
|
throw Error('This should not be happening, but there was no paragraph or list item');
|
||||||
throw Error('This should not be happening, but there was no paragraph');
|
|
||||||
}
|
}
|
||||||
if (paragraph === endAncestor) {
|
// should have the same tag as the start item
|
||||||
|
const endAncestor = findClosestAncestorWithTag(endContainer, startAncestor.tagName);
|
||||||
|
|
||||||
|
if (startAncestor === endAncestor) {
|
||||||
const contentComponent = findClosestAncestorWithClass(startContainer, 'content-component');
|
const contentComponent = findClosestAncestorWithClass(startContainer, 'content-component');
|
||||||
if (contentComponent) {
|
if (contentComponent) {
|
||||||
// our selection is wholly inside the container node, we continue with it
|
// our selection is wholly inside the container node, we continue with it
|
||||||
const position = findPositionInParent(contentComponent);
|
const position = findPositionInParent(contentComponent);
|
||||||
const siblings = Array.from(paragraph.parentElement?.children || []);
|
const siblings = Array.from(startAncestor.parentElement?.children || []);
|
||||||
const positionInTextBlock = siblings.indexOf(paragraph);
|
const positionInTextBlock = siblings.indexOf(startAncestor);
|
||||||
|
|
||||||
const numOfParagraphs = Array.from(contentComponent.children[1].children).filter(
|
const { start, end } = range.toCharacterRange(startAncestor);
|
||||||
(child) => child.nodeName.toLowerCase() === 'p'
|
|
||||||
).length;
|
|
||||||
|
|
||||||
const { start, end } = range.toCharacterRange(paragraph);
|
|
||||||
const uuid = contentComponent.dataset.uuid || '';
|
const uuid = contentComponent.dataset.uuid || '';
|
||||||
const highlightedText: Highlight = {
|
const highlightedText: Highlight = {
|
||||||
contentBlock: contentBlock.id,
|
contentBlock: contentBlock.id,
|
||||||
|
|
@ -134,7 +139,7 @@ export const getSelectionHandler =
|
||||||
console.log(highlightedText);
|
console.log(highlightedText);
|
||||||
|
|
||||||
const positionOfContentBlock = el.getBoundingClientRect();
|
const positionOfContentBlock = el.getBoundingClientRect();
|
||||||
const positionOfSelection = paragraph?.getBoundingClientRect();
|
const positionOfSelection = startAncestor?.getBoundingClientRect();
|
||||||
const offsetTop = positionOfSelection.top - positionOfContentBlock.top;
|
const offsetTop = positionOfSelection.top - positionOfContentBlock.top;
|
||||||
popover
|
popover
|
||||||
.show({
|
.show({
|
||||||
|
|
@ -144,11 +149,6 @@ export const getSelectionHandler =
|
||||||
console.log('chosenColor', color);
|
console.log('chosenColor', color);
|
||||||
highlightedText.color = color;
|
highlightedText.color = color;
|
||||||
onUpdateHighlight(highlightedText);
|
onUpdateHighlight(highlightedText);
|
||||||
// const newHighlight: Highlight = {
|
|
||||||
// contentBlock: contentBlock.id,
|
|
||||||
// contentIndex:
|
|
||||||
//
|
|
||||||
// };
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ interface Options {
|
||||||
offsetTop: number;
|
offsetTop: number;
|
||||||
onChooseColor: (color: string) => void;
|
onChooseColor: (color: string) => void;
|
||||||
// we don't use the id as a param here, because the calling component knows already which entity it is
|
// we don't use the id as a param here, because the calling component knows already which entity it is
|
||||||
onDelete: () => void;
|
onDelete?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -48,7 +48,9 @@ export default {
|
||||||
_reject();
|
_reject();
|
||||||
},
|
},
|
||||||
onDelete() {
|
onDelete() {
|
||||||
onDelete();
|
if (onDelete) {
|
||||||
|
onDelete();
|
||||||
|
}
|
||||||
cleanUp();
|
cleanUp();
|
||||||
},
|
},
|
||||||
onChooseColor,
|
onChooseColor,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue