nemo
nemo

Reputation: 151

Add element to div in a relative position

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>

;

Upvotes: 2

Views: 590

Answers (2)

Jerdine Sabio
Jerdine Sabio

Reputation: 6140

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>

Upvotes: 1

Sushrut Singh Sisodiya
Sushrut Singh Sisodiya

Reputation: 990

Have a look to this code here you can get location on your click and i guess then you can assign this x and y value to you top and left variable

function printMousePos(event) {
  document.body.textContent =
    "clientX: " + event.clientX +
    " - clientY: " + event.clientY;
}

document.addEventListener("click", printMousePos);

Upvotes: 0

Related Questions