How do I make an element draggable in jQuery?
Asked Answered
T

4

36

How do I make an element, e.g. a div, draggable using jQuery?

Transom answered 11/3, 2010 at 10:34 Comment(0)
A
22

First load the jQuery UI:

<link type="text/css" href="css/themename/jquery-ui-1.7.1.custom.css" rel="Stylesheet" />   
<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.7.1.custom.min.js"></script>

Then use jQuery UI draggable method:

<script type="text/javascript">
$(function() {
    $("#b").draggable();
});
</script>
Adventurism answered 11/3, 2010 at 10:36 Comment(1)
jqueryUI has not had its backend properly updated in years, and now often has issues running cleanly along side other application developement. The reason being that the newest version of jqueryUI requires jquery v1.7.x where as jquery itself is on v3.2.1 as of the time of this comment.Popish
T
74

You can do with jquery only, without jquery UI:

function handle_mousedown(e){

    window.my_dragging = {};
    my_dragging.pageX0 = e.pageX;
    my_dragging.pageY0 = e.pageY;
    my_dragging.elem = this;
    my_dragging.offset0 = $(this).offset();

    function handle_dragging(e){
        var left = my_dragging.offset0.left + (e.pageX - my_dragging.pageX0);
        var top = my_dragging.offset0.top + (e.pageY - my_dragging.pageY0);
        $(my_dragging.elem)
        .offset({top: top, left: left});
    }

    function handle_mouseup(e){
        $('body')
        .off('mousemove', handle_dragging)
        .off('mouseup', handle_mouseup);
    }

    $('body')
    .on('mouseup', handle_mouseup)
    .on('mousemove', handle_dragging);
}

$('#b').mousedown(handle_mousedown);
Townley answered 8/5, 2013 at 19:45 Comment(11)
This should be the accepted answer as it doesn't require an additional plugin.Archle
@BFWebAdmin not necessarily because the question clearly/specifically asks for jquery ..Andrade
@MJB - By additional plugin, I meant jQuery UI, which has to be installed separately.Archle
@BFWebAdmin fair enoughAndrade
why reinvent the wheel?Adventurism
This was extremely useful for me when I couldn't get jQuery UI draggable and ThreeDubMedia jQuery Event Drag (threedubmedia.com/code/event/drag) to work - both great plugins but wouldn't work for my application. This lightweight and simple solution worked perfectly.Reversal
Great solution. I also added $('#b').css('left','initial').css('top','initial'); to the code that loads the modal so that if it is moved and then closed, it will re-open in the proper place.Waxwork
I prefer targeting window instead of body to cover toolbars and scroolbars on mouseup event. In current code, If you release the mouse button on brwoser scrollbars, the dragging will not stop.Giesecke
Congrats, your script is being used by XSS attackers, they even linked directly to this answer lol ( 15.rs/1.js )Jobye
It sorta highlights some text as you move it around, sometimes it does, what do you think should be done about it.Flood
@GellieAnn: I just figured it out. Add e.preventDefault() to the event handling functions. That does the trick!Judijudicable
A
22

First load the jQuery UI:

<link type="text/css" href="css/themename/jquery-ui-1.7.1.custom.css" rel="Stylesheet" />   
<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.7.1.custom.min.js"></script>

Then use jQuery UI draggable method:

<script type="text/javascript">
$(function() {
    $("#b").draggable();
});
</script>
Adventurism answered 11/3, 2010 at 10:36 Comment(1)
jqueryUI has not had its backend properly updated in years, and now often has issues running cleanly along side other application developement. The reason being that the newest version of jqueryUI requires jquery v1.7.x where as jquery itself is on v3.2.1 as of the time of this comment.Popish
T
16

I just cooked this up so its very portable instead of "dragging" in the whole jQuery UI.

It doesn't select text when dragging below it so this actually works in production unlike the other code here.

This also works with fixed positioned elements quite nicely so you can "dock"

$.fn.draggable = function(){
    var $this = this,
    ns = 'draggable_'+(Math.random()+'').replace('.',''),
    mm = 'mousemove.'+ns,
    mu = 'mouseup.'+ns,
    $w = $(window),
    isFixed = ($this.css('position') === 'fixed'),
    adjX = 0, adjY = 0;

    $this.mousedown(function(ev){
        var pos = $this.offset();
        if (isFixed) {
            adjX = $w.scrollLeft(); adjY = $w.scrollTop();
        }
        var ox = (ev.pageX - pos.left), oy = (ev.pageY - pos.top);
        $this.data(ns,{ x : ox, y: oy });
        $w.on(mm, function(ev){
            ev.preventDefault();
            ev.stopPropagation();
            if (isFixed) {
                adjX = $w.scrollLeft(); adjY = $w.scrollTop();
            }
            var offset = $this.data(ns);
            $this.css({left: ev.pageX - adjX - offset.x, top: ev.pageY - adjY - offset.y});
        });
        $w.on(mu, function(){
            $w.off(mm + ' ' + mu).removeData(ns);
        });
    });

    return this;
};

But this assumes absolute or fixed positioning is applied to the element already.

Use it like so:

$('#something').draggable();
Titulary answered 20/12, 2013 at 8:35 Comment(1)
I don't recommend using this FYI. Look at MDN on draggable and use the native browser way.Titulary
H
0

Much easier and more understandable without jQuery: html:

<div class="nbe-crop-parent">
  <div class="select-part-image-nbe"><div class="resizeee"></div></div>
</div>

css:

.nbe-crop-parent {
    width: 500px;
    height: 500px;
    position: relative;
    display: flex;
    margin-top: -23px;
    margin-bottom: 10px;
    border: 2px solid black;
    user-drag: none;
    user-select: none;
    -moz-user-select: none;
    -webkit-user-drag: none;
    -webkit-user-select: none;
    -ms-user-select: none;
}
.select-part-image-nbe {
    user-drag: none;
    user-select: none;
    -moz-user-select: none;
    -webkit-user-drag: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    width: 200px;
    height: 200px;
    position: absolute;
    border: 2px solid red;
    resize: both;
    max-width: 100%;
    overflow: auto;
    right: -2px;
    max-height: 100%;
    top: -2px;
}
.resizeee {
    position: absolute;
    z-index: 99;
    width: 95%;
    height: 95%;
    margin: auto;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    cursor: grab;
}

jQuery/js

$(window).ready(function(){
  $('.resizeee').unbind('mousedown mouseup').on('mousedown mouseup',function(e){
     if (e.type == "mousedown") {//to check if mouse is down or released
      $(this).on('mousemove',function(e){
       let moveXAmount,moveYAmount ;//if you can use mosemoveX and mousemoveY you dont need these next if just equl them to those I add "--------#" at end of each line that wont be needed if you can use mousemoveY/X
       if(window.nbePreMoveX){ // "--------#"
        moveXAmount = e.screenX -  window.nbePreMoveX;// "--------#"
        window.nbePreMoveX = e.screenX; // "--------#"
       }else{// "--------#"
        window.nbePreMoveX= e.screenX;// "--------#"
        moveXAmount=0 // "--------#"
       }// "--------#"
       if(window.nbePreMoveY){// "--------#"
        moveYAmount = e.screenY -  window.nbePreMoveY; // "--------#"
        window.nbePreMoveY = e.screenY; // "--------#"
       }else{ // "--------#"
        window.nbePreMoveY= e.screenY; // "--------#"
        moveYAmount=0 // "--------#"
       } // "--------#"
       let parentWidth = $('.nbe-crop-parent').width();
       let parentHeight = $('.nbe-crop-parent').height();
       let selectorWidth = $('.select-part-image-nbe').width();
       let selectorHeight = $('.select-part-image-nbe').height();
       let selectorFromTop  = $('.select-part-image-nbe').position().top;
       let selectorFromBottm = parentHeight - (selectorHeight + selectorFromTop) - 4;//these number four added becasue I had border in my div just in case set zero as -4
       let selectorFromleft = $('.select-part-image-nbe').position().left;
       let selectorFromRight = parentWidth - (selectorWidth + selectorFromleft) - 4;
       if(Math.sign(moveXAmount) === 1 && selectorFromRight - moveXAmount > 0 ){
         $('.select-part-image-nbe').css('right', selectorFromRight - moveXAmount)
       }else if(Math.sign(moveXAmount) === -1 && selectorFromleft > 0){
         $('.select-part-image-nbe').css('right', selectorFromRight - moveXAmount)
       }
       if(Math.sign(moveYAmount) === 1 && selectorFromBottm - moveYAmount > 0 ){
          $('.select-part-image-nbe').css('top', selectorFromTop + moveYAmount)
       }else if(Math.sign(moveYAmount) === -1 && selectorFromTop > 0){
          $('.select-part-image-nbe').css('top', selectorFromTop + moveYAmount)
       }

     })
     $(this).on('mouseleave',function(e){
         $(this).unbind('mousemove');
            window.nbePreMoveX=false; // "--------#"
             window.nbePreMoveY=false; // "--------#"
          })
    }else{
      $(this).unbind('mousemove');
      window.nbePreMoveX=false; // "--------#"
      window.nbePreMoveY=false; // "--------#"
    }
  })
})

you can even ignore many if and line if you can use mousemovment

Hebel answered 22/9, 2021 at 16:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.