Skip to content

Stop drag event when reaching the min or max

How can I stop dragging as soon as the drag hits top and bottom of the .parent?

As you can see the .button is stops as soon as it hits the inner top and bottom of the .parent but the event still continuing! . to test it try to drag the .button to the bottom ot top and do not stop dragging when reaching the end, as you can see the new_top still updating!

$(function() {
    $('.button').mousedown(function(e) {
        if(e.which===1) {
            var button = $(this);
            var parent_height = button.parent().innerHeight();
            var top = parseInt(button.css('top')); //current top position
            var original_ypos = button.css('top','').position().top; //original ypos (without top)
            button.css({top:top+'px'}); //restore top pos
            var drag_min_ypos = 0-original_ypos;
            var drag_max_ypos = parent_height-original_ypos-button.outerHeight();
            var drag_start_ypos = e.clientY;
            $('#log1').text('mousedown top: '+top+', original_ypos: '+original_ypos);
            $(window).on('mousemove',function(e) {
                button.addClass('drag');
                var new_top = top+(e.clientY-drag_start_ypos);
                button.css({top:new_top+'px'});
                if(new_top<drag_min_ypos) { button.css({top:drag_min_ypos+'px'}); }
                if(new_top>drag_max_ypos) { button.css({top:drag_max_ypos+'px'}); }
                $('#log2').text('mousemove min: '+drag_min_ypos+', max: '+drag_max_ypos+', new_top: '+new_top);

            });
            $(window).on('mouseup',function(e) {
                 if(e.which===1) {
                    $('.button').removeClass('drag');
                    $(window).off('mouseup mousemove');
                    $('#log1').text('mouseup');
                    $('#log2').text('');
                 }
            });
        }
    });
});
.parent {
    position: relative;
    display: block;
    padding: 0px;
    margin: 20px;
    width:45px;
    height: 200px;
    border: 1px solid black;
}
.button {
    position: absolute;
    top: 0;
    display: table;
    margin-bottom: 2px;
    height: 25px;
    clear: both;
}
.button.drag { z-index: 99; color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="parent" class="parent">
    <button id="button1" class="button">Drag</button>

</div>
<div id="log1"></div>
<div id="log2"></div>

Answer

You can add this line inside your check:

$(this).off('mousemove');

Which removes the mousemove listener when you hit the max y position.

$(function() {
    $('.button').mousedown(function(e) {
        if(e.which===1) {
            var button = $(this);
            var parent_height = button.parent().innerHeight();
            var top = parseInt(button.css('top')); //current top position
            var original_ypos = button.css('top','').position().top; //original ypos (without top)
            button.css({top:top+'px'}); //restore top pos
            var drag_min_ypos = 0-original_ypos;
            var drag_max_ypos = parent_height-original_ypos-button.outerHeight();
            var drag_start_ypos = e.clientY;
            $('#log1').text('mousedown top: '+top+', original_ypos: '+original_ypos);
            $(window).on('mousemove',function(e) {
                button.addClass('drag');
                var new_top = top+(e.clientY-drag_start_ypos);
                button.css({top:new_top+'px'});
                
                if(new_top < drag_min_ypos) {  
                  button.css({top:drag_min_ypos+'px'}); 
                }
                
                if (new_top > drag_max_ypos) {
                  button.css({top:drag_max_ypos+'px'}); 
                  $(this).off('mousemove');   /// <<< ------ HERE
                }
                $('#log2').text('mousemove min: '+drag_min_ypos+', max: '+drag_max_ypos+', new_top: '+new_top);

             
            });
            $(window).on('mouseup',function(e) {
                 if(e.which===1) {
                    $('.button').removeClass('drag');
                    $(window).off('mouseup mousemove');
                    $('#log1').text('mouseup');
                    $('#log2').text('');
                 }
            });
        }
    });
});
.parent {
    position: relative;
    display: block;
    padding: 0px;
    margin: 20px;
    width:45px;
    height: 200px;
    border: 1px solid black;
}
.button {
    position: absolute;
    top: 0;
    display: table;
    margin-bottom: 2px;
    height: 25px;
    clear: both;
}
.button.drag { z-index: 99; color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="parent" class="parent">
    <button id="button1" class="button">Drag</button>

</div>
<div id="log1"></div>
<div id="log2"></div>