Given the HTML as a string, the Xpath and offsets. I need to highlight the word.
In the below case I need to highlight Child 1
HTML text:
<html> <body> <h2>Children</h2>Joe has three kids:<br/> <ul> <li> <a href="#">Child 1 name</a> </li> <li>kid2</li> <li>kid3</li> </ul> </body> </html>
XPATH as : /html/body/ul/li[1]/a[1]
Offsets: 0,7
Render - I am using react
in my app. The below is what I have done so far.
public render(){ let htmlText = //The string above let doc = new DOMParser().parseFromString(htmlRender,'text/html'); let ele = doc.evaluate("/html/body/ul/li[1]/a[1]", doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); //This gives the node itself let spanNode = document.createElement("span"); spanNode.className = "highlight"; spanNode.appendChild(ele); // Wrapping the above node in a span class will add the highlights to that div //At this point I don't know how to append this span to the HTML String return( <h5> Display html data </h5> <div dangerouslySetInnerHTML={{__html: htmlText}} /> )
I want to avoid using jquery. Want to do in Javascript(React too) if possible!
Edit:
So if you notice the Render
function it is using dangerouslySetHTML
. My problem is I am not able manipulate that string which is rendered.
2 Answers
Answers 1
This is what I ended up doing.
public render(){ let htmlText = //The string above let doc = new DOMParser().parseFromString(htmlRender,'text/html'); let xpathNode = doc.evaluate("/html/body/ul/li[1]/a[1]", doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); const highlightedNode = xpathNode.singleNodeValue.innerText; const textValuePrev = highlightedNode.slice(0, char_start); const textValueAfter = highlightedNode.slice(char_end, highlightedNode.length); xpathNode.singleNodeValue.innerHTML = `${textValuePrev} <span class='pt-tag'> ${highlightedNode.slice(char_start, char_end)} </span> ${textValueAfter}`; return( <h5> Display html data </h5> <div dangerouslySetInnerHTML={{__html: doc.body.outerHTML}} /> )
Answers 2
Xpath is inherently cross component, and React components shouldn't know much about each other. Xpath also basically requires all of the DOM to be created in order to query it. I would render your component first, then simply mutate the rendered output in the DOM using the Xpath selector.
https://jsfiddle.net/69z2wepo/73860/
var HighlightXpath = React.createClass({ componentDidMount() { let el = document.evaluate(this.props.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); el.singleNodeValue.style.background = 'pink'; }, render: function() { return this.props.children; } });
Usage:
<HighlightXpath xpath="html//body//div/p/span"> ... app ... </HighlightXpath>
0 comments:
Post a Comment