diff --git a/client/src/directives/highlight.ts b/client/src/directives/highlight.ts index 748cc7cd..9ab8c1e5 100644 --- a/client/src/directives/highlight.ts +++ b/client/src/directives/highlight.ts @@ -32,9 +32,17 @@ const isInsideViewport = (position: number) => { 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; - while (currentNode && currentNode.nodeName.toLowerCase() !== tag && currentNode.nodeName.toLowerCase() !== 'body') { + while ( + currentNode && + !tagList.includes(currentNode.nodeName.toLowerCase()) && + currentNode.nodeName.toLowerCase() !== 'body' + ) { currentNode = currentNode.parentNode; } if (currentNode) { @@ -93,34 +101,31 @@ export const getSelectionHandler = const rect = el.getBoundingClientRect(); if (isInsideViewport(rect.top) || isInsideViewport(rect.bottom)) { // 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 - const selection = rangy.getSelection(); if (selection.rangeCount && !selection.isCollapsed) { + // ⬆️ sat least one selection exists and is not of length 0 const range = selection.getRangeAt(0); if (range.intersectsNode(el)) { // the selection is inside our container, so we can do something with it const { startContainer, endContainer } = range; - const paragraph = findClosestAncestorWithTag(startContainer, 'p'); - const endAncestor = findClosestAncestorWithTag(endContainer, 'p'); - - if (!paragraph) { - throw Error('This should not be happening, but there was no paragraph'); + const startAncestor = findClosestAncestorWithTag(startContainer, ['p', 'li']); + // const endAncestor = findClosestAncestorWithTag(endContainer, 'p'); + if (!startAncestor) { + throw Error('This should not be happening, but there was no paragraph or list item'); } - 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'); if (contentComponent) { // our selection is wholly inside the container node, we continue with it const position = findPositionInParent(contentComponent); - const siblings = Array.from(paragraph.parentElement?.children || []); - const positionInTextBlock = siblings.indexOf(paragraph); + const siblings = Array.from(startAncestor.parentElement?.children || []); + const positionInTextBlock = siblings.indexOf(startAncestor); - const numOfParagraphs = Array.from(contentComponent.children[1].children).filter( - (child) => child.nodeName.toLowerCase() === 'p' - ).length; - - const { start, end } = range.toCharacterRange(paragraph); + const { start, end } = range.toCharacterRange(startAncestor); const uuid = contentComponent.dataset.uuid || ''; const highlightedText: Highlight = { contentBlock: contentBlock.id, @@ -134,7 +139,7 @@ export const getSelectionHandler = console.log(highlightedText); const positionOfContentBlock = el.getBoundingClientRect(); - const positionOfSelection = paragraph?.getBoundingClientRect(); + const positionOfSelection = startAncestor?.getBoundingClientRect(); const offsetTop = positionOfSelection.top - positionOfContentBlock.top; popover .show({ @@ -144,11 +149,6 @@ export const getSelectionHandler = console.log('chosenColor', color); highlightedText.color = color; onUpdateHighlight(highlightedText); - // const newHighlight: Highlight = { - // contentBlock: contentBlock.id, - // contentIndex: - // - // }; }, }) .then(() => { diff --git a/client/src/helpers/popover.ts b/client/src/helpers/popover.ts index bdac13f8..fd780367 100644 --- a/client/src/helpers/popover.ts +++ b/client/src/helpers/popover.ts @@ -8,7 +8,7 @@ interface Options { offsetTop: number; onChooseColor: (color: string) => void; // 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 { @@ -48,7 +48,9 @@ export default { _reject(); }, onDelete() { - onDelete(); + if (onDelete) { + onDelete(); + } cleanUp(); }, onChooseColor,