Sunday, March 26, 2017

Highlighting when HTML and Xpath is given

Leave a Comment

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> 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment