I'm trying to implement highlighter to my blog project using React however I couldn't find any useful library to implement it. Basically I want to implement replica of Medium's Highlighter to my article pages.
After the text selection done, if the user activated the highlighter tool, should be able to highlight the text. Since it requires DOM manipulation I haven't come across the full implementation of the Highlighter the way I wanted to.
What I want to do
- User should activate the highlighter.
- When the user selects text on the specified area of the articles page, Popover should come up and the user be able select color.
- If highlighted text mouseovered, user should see Popover to change the color remove the color.
I found some similar tools;
- Link Closest one however it's not getting the which area to highlight and popover modification is not easy.
- Link
- Link Can't manipulate the selected text.
I also tried similar JavaScript example however i got error on this methods.link
Currently, I'm trying to write my own component if I can finish it, I will share the source code.
This is the component I wrote, after the text selection done how can i wrap the selected text area with span and can track multiple highlighted texts to remove without breaking the React. I haven't implemented popover yet. I call this component on article page. Ref comes from the article div.
//articleRef is the id of article area where i want to Highlighter to work.
const Highlighter = ({articleRef}) => {
const { isActive } = useSelector((state) => state.highlighter)
const [selectedText, setSelection] = useState("")
const [selectedNode, setNodeSelection] = useState("")
const [selectedNodes, setNodesSelection] = useState()
useEffect(() => {
document.onselectionchange = function() {
console.log(isActive)
console.log(articleRef.current.id)
// check if the selection done on the article area and check highlighter tool is active
if(articleRef.current.id === 'article-area' && isActive === true ){
console.log("Highlighter is active")
if(document.getSelection() !== (undefined || null ) ){
setNodeSelection(document.getSelection())
}
for(let i = 0; i < selectedNode.rangeCount; i++) {
if( selectedNode.getRangeAt(i) !== (undefined || null )){
console.log(selectedNode.getRangeAt(i))
setSelection(selectedNode.getRangeAt(i).cloneContents())
}
};
console.log(selectedNode)
console.log(selectedText)
}
}
}, [selectedText, selectedNode, isActive, articleRef])
return null;
}
You can use the
getSelectionAPI to get the highlighted text. You can make it so that when the user clicks, you get the mouse's position (1), create a element (2) there (which is the tooltip/popup in this case) and use thegetSelectionAPI to get the selected text. I recommend using some react hook instead ofgetSelectionas its easier.(1) - The mouse's position is reported on the event object received by a handler in onmousemove event
(2) - You could also have a hidden element which will be moved to the cursor's position using CSS and make it visible