0

I was trying to make a div which could be moved to any position like drag and drop function. I used the following approach:

var songs = {};
songs.clickedM = 0;
$(".song-progress .current-position")[0].addEventListener("mousedown", function(down2) {
songs.clickedM = 1;
var intpos2 = down2.clientX;

$(".song-progress .current-position")[0].addEventListener( "mousemove", function(Dmove2) {

    if(songs.clickedM == 1) {           

        if (Dmove2.clientX <= $(".song-progress").offset().left) {
            $(".song-progress .current-position")[0].style.left = "0px";
            
        }
        else if( Dmove2.clientX >= ($(".song-progress").outerWidth() + $(".song-progress").offset().left)) {
            $(".song-progress .current-position")[0].style.left = ( $(".song-progress").outerWidth() - 14) + "px";
           
        }
        else {
            $(".song-progress .current-position")[0].style.left = (Dmove2.clientX - $(".song-progress").offset().left ) + "px";
           
        }
    }

});

});

$("body")[0].addEventListener("mouseup", function() {


songs.clickedM = 0;
   
});
.container {
  padding: 100px;
  width: 700px;
  height: 500px;
  background-color: lightgray;
}
.song-progress {
        position: absolute;
        top: 84px;
        right: 15px;
        height: 5px;
        width: calc(100% - 135px);
        background-color: white;
    }
 .current-progress{
        position: absolute;
        left: 0;
        width: 0px;
        height: 5px;
        background-color: #bbb;
    }
.current-time {
        position: absolute;
        bottom: 5px;
        font-size: 10px;
        left: 0;
        font-family: "Times New Roman"
    }
 .total-time {
        position: absolute;
        bottom: 5px;
        right: 0;
        font-size: 10px;
        font-family: "Times New Roman"
    }
 .current-position {
        height: 9px;
        width: 15px;
        background-color: #00cdff;
        position: absolute;
        top: -2.5px;
        left: 1px;
        cursor: pointer;
        border-radius: 5px;
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
 <div class="song-progress">
                <div class="current-time">1:21</div>
                <div class="total-time">5:37</div>
                <div class="current-progress"></div>
                <div class="current-position"></div>
              </div>
              </div>

I noticed that songs.clickedM never becomes 0, even when mouse key is released. My guess is that the mousemove event listener is a function which is acting like a function closure. And when the mouse moves for the first time after first click it accesses a copy of songs.clickedM not the original. It is unaware of the fact that the original variable songs.clickedM has actually been changed to 0.

How do I make the value of songs.clickedM 0 for mousemove event listener when the key is not pressed?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user31782
  • 7,087
  • 14
  • 68
  • 143
  • If you add a runnable [mcve] to the question using Stack Snippets (the `<>` toolbar button), it'll be easier for people to give you good answers. – T.J. Crowder Jun 19 '16 at 17:06
  • @T.J.Crowder I have added a similar version which still reproduces the problem. – user31782 Jun 19 '16 at 17:26
  • Every time you click mouse down on `.current-position`, you add a new mousemove listener. You need to remove the listener in mouseup handler. Also depending on other elements and CSS of the page, `body` might not be as large as you think it is. I'd rather attached the mouseup listener to `document` or `window`. – Teemu Jun 19 '16 at 17:27
  • The first thing is to remove the `alert`s. `alerts` mess all kinds of things up. :-) – T.J. Crowder Jun 19 '16 at 17:27
  • @T.J.Crowder This is how I debug the problem. And this has been always useful. E.g. in the current situation the alerts keep popping up. Means `mousemove` event is repeating or is stuck in a loop. – user31782 Jun 19 '16 at 17:35
  • @Teemu I don't know how to remove an event handler. And why would that be useful? – user31782 Jun 19 '16 at 17:37
  • 1
    @user31782: `alert` screws with the focus and brings the script to a screching halt. Use the fully-featured debugger built into your browser. That's what it's for. Regarding removing the handler: As I said in the answer below, you're **adding** them repeatedly, so you'll have more and more of them every time you press the mouse down. They'll all get called. – T.J. Crowder Jun 19 '16 at 17:57
  • @T.J.Crowder I have removed alerts. You can see the problem when while dragging the cyan colored button we select text too. – user31782 Jun 26 '16 at 12:46

1 Answers1

1

My guess is that the mousemove event listener is a function which is acting like a function closure.

It's not acting like a closure. It is a closure. :-)

And when the mouse moves for the first time after first click it accesses a copy of songs.clickedM not the original. It is unaware of the fact that the original variable songs.clickedM has actually been changed to 0.

No. Closures have access to the variables they close over, not a copy of the variables they close over. Even if they received a copy, the variable being closed over in this case is songs, which is just a reference to an object; a copy of it would still refer to the same object, with the same clickedM property. All of your even handlers are using the same songs variable and the same clickedM property on the object it refers to. The problem lies elsewhere.

Where that is will require debugging, but one red flag that shows up is that the code is adding a new mousemove handler every time the mouse is pressed on the element, even if it's been added previously. So those mousemove handlers start stacking up.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • The problem was something else. I had to use `event.preventDefault()` on mousedown event. Because when the div was dragged the text could also be selected along. And then browser's default drag and drop action initiated. It is something similar to this problem http://stackoverflow.com/questions/13236484/mouseup-not-working-after-mousemove-on-img – user31782 Jun 26 '16 at 12:43
  • Although I don't understand why I don't have to use `event.preventDefault`on `mousemove` event now. The drag drop problem arises only in `mousemove` situation. – user31782 Jun 26 '16 at 12:45