Unbind not working as expected

Hi.

I’m trying to create a scroll bar through javascript with the help of jquery. What I’m trying to accomplish is:

  1. When the user mouse’s down, it fires off an event (mouse move) and allow the user to scroll.
  2. When the user mouse’s up, it should unbind the event, so that the mouse move is not in effect any more.

But unbind is not working as expected. I looked up the documentation, and it seems correct.


$(document).ready(function() {
  $('#scrollBar').mousedown(function(e) {
    draggable.init(e);
  }).mouseup(function() {
    $(this).unbind('mousemove', draggable.init);
  });
});

var draggable = {
  init: function(e) {
    var min = -100;
    var max = 100;
    var initial = $('#value').val();
    
    $('#scrollBar').mousemove(function(e) {
      $(this).css({'left' : e.pageX});
    });
  }
};

You aren’t specifying the correct function to unbind. You passed an anonymous function to bind(), not draggable.init. Well, you didn’t directly call bind, but .mousedown() is just a convenience method for it.

Use a named function, or even just unbind all handlers for the mousemove event.

You mean like this?


$(document).ready(function() {
  $('#scrollBar').mousedown(function(e) {
    drag(e);
    //draggable.init(e);
  }).mouseup(function() {
    $(this).unbind('mousemove', drag);
    //$(this).unbind('mousemove', draggable.init);
  });
});

function drag(e) {
  var min = -100;
  var max = 100;
  var initial = $('#value').val();
  
  $('#scrollBar').mousemove(function(e) {
    $(this).css({'left' : e.pageX});
  });
}

That doesn’t work either.

I tried to unbind all mousemove events but it starts to act all funky.

For the event to completely be removed with that method, I have to make sure to mouse up right on top of the ID otherwise it doesn’t unbind.

$(‘#scrollBar’).unbind(‘mousemove’);

That’s what I did (but I had $(this) instead) when I tried that method. But it didn’t work as I had to have my mouse over the ID before I could let go of it otherwise the unbind event would not happen.

Let me show you what I mean:



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Scrolls</title>
<script src="../jquery.js" type="text/javascript"></script>
<style type="text/css">
<!--
	.box {
	 float: left;
	 width: 200px;
   margin: 0;
   padding: 2px;
   border: 1px solid #000000;
	}
  
  .input {
    width: 100px;
    height: 25px;
    margin: 0 auto;
    padding: 0;
  }
  
  .bar {
    position: relative;
    width: 150px;
    height: 25px;
    margin: 0;
    padding: 0;
    border: 1px solid #000000;
  }
  
  .scrollBar {
    position: absolute;
    width: 15px;
    height: 15px;
    margin: 5px 0 0 -15px;
    left: 49&#37;;
    padding: 0;
    background: #000000;
    cursor: pointer;
  }
  
  .clearFix {
    clear: both;
  }
-->
</style>
<script type="text/javascript">
$(document).ready(function() {
  $('#scrollBar').mousedown(function(e) {
    //drag(e);
    draggable.init(e);
  }).mouseup(function() {
    $('#scrollBar').unbind('mousemove');
    //$(this).unbind('mousemove', drag);
    //$(this).unbind('mousemove', draggable.init);
  });
});

function drag(e) {
  var min = -100;
  var max = 100;
  var initial = $('#value').val();
  
  $('#scrollBar').mousemove(function(e) {
    $(this).css({'left' : e.pageX});
  });
}

var draggable = {
  init: function(e) {
    var min = -100;
    var max = 100;
    var initial = $('#value').val();
    
    $('#scrollBar').mousemove(function(e) {
      $(this).css({'left' : e.pageX});
    });
  }
};
</script>
</head>

<body>

<div class="box">
  <input type="text" disabled="" value="0" class="input" id="value" />
  
  <div class="bar"><div class="scrollBar" id="scrollBar"></div></div>
</div>

</body>
</html>

Ok I see what you mean. You would need to put the mouseup event handler on a larger container, like maybe the entire window.

I tried attaching it to the body, but it doesn’t work correctly.


$(document).ready(function() {
  $('body').mousedown(function(e) {
    draggable.init(e);
  }).mouseup(function() {
    $(this).unbind('mousemove');
});

EDIT:

This is the new javascript I’ve been messing with, although it still gives me the same issues.


$(document).ready(function() {
  $('#scrollBar').mousedown(function() {
    $('body').bind('mousedown', draggable.init)
             .bind('mouseup', draggable.stop);
  });
});

var draggable = {
  init: function(e) {
    var min = -100;
    var max = 100;
    var initial = $('#value').val();
    
    $('#scrollBar').mousemove(function(e) {
      $(this).css({'left' : e.pageX});
    });
  },
  
  stop: function() {
    $('#scrollBar').unbind('mousemove');
  }
};

Alright I got the majority of it working. I’m hoping you can help me out in the last part of it.

I’m still having issues with the mouse up event. It works as intended when you let go of the mouse within the DIV. But if you let go of the mouse outside the DIV, it doesn’t unbind it right. I thought the fix would be to bind the event to the body, but no such luck.

To reproduce the problem:

  1. Mouse down on the container.
  2. Move your mouse outside the scroll bar and move the box around a little.
  3. Let go of the box. At this point, the box should not be moving, but you can still move it even though you unbinded it on mouse up.
  4. To stop the box from moving, click the box again and it will stop moving.

$(document).ready(function() {
  $('#scrollBar').scrollbar({
    min: -100,
    initial: 0,
    max: 150,
    box: 15
  });
});

(function($) {
  $.fn.scrollbar = function(options) {
    var _self = $(this);
    var defaults = {
      min: -100,
      initial: 0,
      max: 100,
      box: 15
    };
    var options = $.extend(defaults, $.fn.scrollbar.defaults, options);
    
    _self.mousedown(function() {
      $('body').mousemove(function(e) {
        var x = e.pageX;
        
        if (x <= options.max && x >= options.box)
          _self.css({'left' : x});
      });
    }).mouseup(function() {
      $('body').unbind('mousemove');
    });
    
    return this;
  };
})(jQuery);

Hope you can see what I’m not seeing. Thanks! :slight_smile:

_self will not be likely to refer to the window or body under normal use. It’s going to refer to #scrollBar

Again, use the mouseup event that occurs on the window, to unbind your mousemove handler. You would do this like
$(window).mouseup(myFunctionThatUnbinds);