Add element to div in a relative position

nemo :

I'm trying to build something like the highlight feature in Medium. In the click event, I need to add an element that will be in a position: absolute to his parent where the user clicked (not the body since the parent is overflow: scroll;)

The issue is to add the mark element in the correct place.

  1. How can I find the top and left position of what the user highlighted?
  2. How can I add the marking relative to the article element? Whenever the user scrolls, I need the mark element to stay over the highlighted text.

I'm trying to set them with the below code;

mark.setAttribute("style", `top:${top}px`);
mark.setAttribute("style", `left:${left}px`);

https://codepen.io/nemo369/pen/ExjQgKy

const article =document.querySelector(`article`);

article.addEventListener('mouseup', function () {
  var result =  window.getSelection().toString();
  const oldMark =document.querySelector(`.mark`);
  if(oldMark){
    article.removeChild(oldMark);
  }
  window.getSelection().empty()
  if(result){
    let mark = document.createElement('mark');
    mark.innerText =  `${result}`;
    mark.classList.add('mark');
    var top = 5;
    var left = 15
mark.setAttribute("style", `top:${top}px`);
mark.setAttribute("style", `left:${left}px`);
    article.appendChild(mark);
  }
});
main{
     display: flex;
flex-direction:column;
  height:100vh;
  align-items:center;
  justify-content: center;
}
article{
  max-height:30%;
overflow:scroll;
  flex:0 0 50vw;
  position: relative;
}
.mark{
      position: absolute;
  top:50%;
  left:50%;
}
<main>
  <article>
    
    <p>I'm trying to build something like the highlight feature in Medium.<br>
The issue is that in the click event I need to add an element that will be in a <strong>position absolute</strong> to his parent and not the body since the parent is <strong>overflow: scroll;<strong><br>

How can I find those x and y conditions?

 </p>
          
    <p>I'm trying to build something like the highlight feature in Medium.<br>
The issue is that in the click event I need to add an element that will be in a <strong>position absolute</strong> to his parent and not the body since the parent is <strong>overflow: scroll;<strong><br>

How can I find those x and y conditions?

 </p>
          
    <p>I'm trying to build something like the highlight feature in Medium.<br>
The issue is that in the click event I need to add an element that will be in a <strong>position absolute</strong> to his parent and not the body since the parent is <strong>overflow: scroll;<strong><br>

How can I find those x and y conditions?

 </p>
  </article>
  
</main>

;

Jerdine Sabio :

Good question, I had to go back to javascript basics. Fortunately, I found the key-- there are offsetTop, offsetLeft properties!

So in this script, on mousedown, we're getting the event click location then subtract the offset position of the article element.

The offset position refers to how far the target element is from the start of the document.

EDIT: To handle the vertical scroll position inside the article, I added article.scrollTop on computation.

Run the demo below.

const article = document.querySelector(`article`);

var x;
var y;

article.addEventListener('mousedown', function() {
  x = event.clientX;
  y = event.clientY;

  y = y - article.offsetTop + article.scrollTop - 5.5;
  x = x - article.offsetLeft + 1;
})

article.addEventListener('mouseup', function() {
  var result = window.getSelection().toString();
  const oldMark = document.querySelector(`.mark`);
  const body = document.querySelector(`body`);

  if (oldMark) {
    article.removeChild(oldMark);
  }
  window.getSelection().empty()
  if (result) {
    let mark = document.createElement('mark');
    mark.innerText = `${result}`;
    mark.classList.add('mark');
    mark.setAttribute("style", `top:${y}px; left:${x}px;`);
    article.appendChild(mark);
  }
});
main {
  display: flex;
  flex-direction: column;
  height: 100vh;
  align-items: center;
  justify-content: center;
}

article {
  max-height: 50%;
  overflow: scroll;
  flex: 0 0 50vw;
  position: relative;
}

.mark {
  position: absolute;
  top: 50%;
  left: 50%;
}
<main>
  <article>

    <p>I'm trying to build something like the highlight feature in Medium.<br> The issue is that in the click event I need to add an element that will be in a <strong>position absolute</strong> to his parent and not the body since the parent is <strong>overflow: scroll;<strong><br>

How can I find those x and y conditions?

 </p>
          
    <p>I'm trying to build something like the highlight feature in Medium.<br>
The issue is that in the click event I need to add an element that will be in a <strong>position absolute</strong> to his parent and not the body since the parent is <strong>overflow: scroll;<strong><br>

How can I find those x and y conditions?

 </p>
          
    <p>I'm trying to build something like the highlight feature in Medium.<br>
The issue is that in the click event I need to add an element that will be in a <strong>position absolute</strong> to his parent and not the body since the parent is <strong>overflow: scroll;<strong><br>

How can I find those x and y conditions?

 </p>
  </article>
  
</main>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=346577&siteId=1