Search code examples
javascripthtmljquerycsscursor-position

changing position relative to mouse pointer


I looked for many similar question but couldn't solve my issue. Here I have pasted only a single list item out of my code. I need to create a span on mousemove event over the list item, and set its left-offset from its parent as the mouse moves. As I haven't ever tried any such thing, I experimented a lot with the code to get to this-

document.querySelector("li a").addEventListener("mousemove",(event)=> {

			let span;
			let alreadyHasSpan =    event.target.hasChildNodes().length > 1; //default length=1

			if(!alreadyHasSpan) {
				span = $(`<span class="a-effect"></span>`);
				span.appendTo(event.target);
			}

			let targetLeftPos = event.target.getBoundingClientRect().left;

				span.css("left",`${event.clientX-targetLeftPos}px`);


			$(this).mouseleave(function () { 
				span.remove();
			});
}, false);
a {
  position: relative;
}
.a-effect {
	position: absolute; left: 0;
	height: 100%;
	width: 2%;
	background: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<li class="nav-item active">
		<a href="/" class="nav-link">Product</a>	
</li>

On my browser, the span moves but with trailing signs behind it-

Apart from the trailing signs, it oftens misses to show the span. On this question's snippets, it's even worse to show the issue.

What's the issue and how could I fix it?


Solution

  • As per your question, the issue is that you're adding a new span everytime the mouse moves. I am guessing you only want to add it when mouse enters, and remove it once the mouse leaves.

    I have tried to keep your code as much as possible and change only what is causing your issue.

    document.querySelector("li a").addEventListener("mouseenter", (event) => {
    
      let span;
      let alreadyHasSpan = event.target.childNodes.length > 1; //default length=1
    
      if (!alreadyHasSpan) {
        span = $(`<span class="a-effect"></span>`);
        span.appendTo(event.target);
      }
    });
    
    document.querySelector("li a").addEventListener("mousemove", (event) => {
      let targetLeftPos = event.target.getBoundingClientRect().left;
      if (event.target.childNodes.length > 1) {
        let span = event.target.childNodes[1];
        $(span).css("left", `${event.clientX-targetLeftPos}px`);
      }
    });
    
    document.querySelector("li a").addEventListener("mouseleave", (event) => {
      if (event.target.childNodes.length > 1) {
        let span = event.target.childNodes[1];
        span.remove();
      }
    });
    a {
      position: relative;
    }
    
    .a-effect {
      position: absolute;
      left: 0;
      height: 100%;
      width: 2%;
      background: black;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <li class="nav-item active">
      <a href="/" class="nav-link">Product</a>
    </li>