58

I'm trying to make bootstrap twitter dialog modal draggable with this jquery plugin:

http://threedubmedia.com/code/event/drag#demos

but it doesn't work.

var $div = $('html');
console.debug($('.drag'));
$('#modalTest')
    .drag("start", function(ev, dd) {
        dd.limit = $div.offset();
        dd.limit.bottom = dd.limit.top + $div.outerHeight() - $(this).outerHeight();
        dd.limit.right = dd.limit.left + $div.outerWidth() - $(this).outerWidth();
    })
    .drag(function(ev, dd) {
        $(this).css({
            top: Math.min(dd.limit.bottom, Math.max(dd.limit.top, dd.offsetY))
            , left: Math.min(dd.limit.right, Math.max(dd.limit.left, dd.offsetX))
        });
    }); 

Have you idea how can I do it?

Ali Soltani
  • 9,589
  • 5
  • 30
  • 55
paganotti
  • 5,591
  • 8
  • 37
  • 49
  • http://stackoverflow.com/questions/12591597/twitter-bootstrap-modal-form-how-to-drag-and-drop using JQuery UI – mccannf Oct 18 '12 at 18:48
  • 2
    None of the answers below are great because [bootstrap conflicts with jQuery UI](http://stackoverflow.com/q/9048214/586086). – Andrew Mao Apr 04 '14 at 16:25
  • @AndrewMao, see http://stackoverflow.com/questions/12591597/twitter-bootstrap-modal-form-how-to-drag-and-drop/24562349#24562349. – Bryan Larsen Jul 03 '14 at 20:00
  • @AndrewMao my answer is only using jQuery, no pluggin. See: https://stackoverflow.com/a/51824269/1914034 – Below the Radar Feb 12 '19 at 13:46

10 Answers10

100
$("#myModal").draggable({
    handle: ".modal-header"
}); 

it works for me. I got it from there. if you give me thanks please give 70% to Andres Ilich

Community
  • 1
  • 1
Mizbah Ahsan
  • 1,252
  • 1
  • 8
  • 17
60

You can use the code below if you dont want to use jQuery UI or any third party pluggin. It's only plain jQuery.

This answer works well with Bootstrap v3.x . For version 4.x see @User comment below

$(".modal").modal("show");

$(".modal-header").on("mousedown", function(mousedownEvt) {
    var $draggable = $(this);
    var x = mousedownEvt.pageX - $draggable.offset().left,
        y = mousedownEvt.pageY - $draggable.offset().top;
    $("body").on("mousemove.draggable", function(mousemoveEvt) {
        $draggable.closest(".modal-dialog").offset({
            "left": mousemoveEvt.pageX - x,
            "top": mousemoveEvt.pageY - y
        });
    });
    $("body").one("mouseup", function() {
        $("body").off("mousemove.draggable");
    });
    $draggable.closest(".modal").one("bs.modal.hide", function() {
        $("body").off("mousemove.draggable");
    });
});
.modal-header {
    cursor: move;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>

<div class="modal fade" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title">Modal title</h4>
      </div>
      <div class="modal-body">
        <p>One fine body&hellip;</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div>
Below the Radar
  • 7,321
  • 11
  • 63
  • 142
  • 9
    Best answer. The solution is not depended on jQuery-ui. – Marcus Frenkel Jun 02 '19 at 20:33
  • 2
    This works but in bootstrap 4 the dialog would jump around a bit when you start dragging. I changed the line `$draggable.closest(".modal-dialog").offset...` to `$draggable.closest(".modal-content").offset...` and now it works correctly. – User May 08 '20 at 00:38
34

The top-ranked solution (by Mizbah Ahsan) is not quite right ...but is close. If you apply draggable() to the modal dialog element, the browser window scroll bars will drag around the screen as you drag the modal dialog. The way to fix that is to apply draggable() to the modal-dialog class instead:

$(".modal-dialog").draggable({
    handle: ".modal-header"
});

Thanks!

IdahoB
  • 738
  • 6
  • 14
8

Like others said, the simpliest solution is just call draggable() function from jQuery UI just after showing modal:

$('#my-modal').modal('show')
              .draggable({ handle: ".modal-header" });

But there is a several problems with compatibility between Bootstrap and jQuery UI so we need some addition fixes in css:

.modal
{
    overflow: hidden;
}
.modal-dialog{
    margin-right: 0;
    margin-left: 0;
}
.modal-header{      /* not necessary but imo important for user */
    cursor: move;
}
1_bug
  • 5,505
  • 4
  • 50
  • 58
6

use the jquery UI draggable, much simpler http://jqueryui.com/draggable/

Slim Fadi
  • 1,076
  • 10
  • 14
5

i did this:

$("#myModal").modal({}).draggable();

and it make my very standard/basic modal draggable.

not sure how/why it worked, but it did.

Gordon
  • 393
  • 1
  • 3
  • 8
  • you can add alot of options and events to a singular jquery selection. do .hide() after draggable and it'll hide. I dont think you need the brackets inside the modal options. – Havihavi Aug 22 '15 at 13:16
3

For the mouse cursor (with jQuery UI) :

$('#my-modal').draggable({
    handle: ".modal-header"
});

For the touch cursor (with jQuery):

var box = null;
var touchobj = null;
var position = {'x':0, 'y':0};
var positionbox = {'x':0, 'y':0};

// init touch
$('.modal-header').on('touchstart', function(e){
    box = $(this).closest('.modal-dialog');
    touchobj = e.changedTouches[0];

    // take position touch cursor
    position['x'] = touchobj.pageX;
    position['y'] = touchobj.pageY;

    //take original position box to move with touch
    positionbox['x'] = parseInt(box.css('left'));
    positionbox['y'] = parseInt(box.css('top'));

    e.preventDefault();
});

// on move touch
$('.modal-header').on('touchmove', function(e){
    var dist = {'x':0, 'y':0};
    touchobj = e.changedTouches[0];

    // we calculate the distance of move
    dist['x'] = parseInt(touchobj.clientX) - position['x'];
    dist['y'] = parseInt(touchobj.clientY) - position['y'];

    // we apply the movement distance on the box
    box.css('left', positionbox['x']+dist['x'] +"px");
    box.css('top', positionbox['y']+dist['y'] +"px");

    e.preventDefault();
});

The addition of the 2 solutions is compatible

Snoozer
  • 585
  • 1
  • 8
  • 16
2

In my own case, i had to set backdrop and set the top and left properties before i could apply draggable function on the modal dialog. Maybe it might help someone ;)

if (!($('.modal.in').length)) {       
$('.modal-dialog').css({
     top: 0,
     left: 0
   });
}
$('#myModal').modal({
  backdrop: false,
   show: true
});

$('.modal-dialog').draggable({
  handle: ".modal-header"
});
Rotimi
  • 4,783
  • 4
  • 18
  • 27
0

In my case I am enabling draggable. It works.

var bootstrapDialog = new BootstrapDialog({
    title: 'Message',
    draggable: true,
    closable: false,
    size: BootstrapDialog.SIZE_WIDE,
    message: 'Hello World',
    buttons: [{
         label: 'close',
         action: function (dialogRef) {
             dialogRef.close();
         }
     }],
});
bootstrapDialog.open();

Might be it helps you.

Jugal Panchal
  • 1,448
  • 16
  • 20
0

You can use jQuery UI Just link jquery UI to your project. Little bit of css is needed for removing transition given by bootstrap on "modal-content" element.

<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css"/>
<style>
    .modal.fade.ui-draggable-dragging {
        -moz-transition: none;
        -o-transition: none;
        -webkit-transition: none;
        transition: none;
    }
</style>
<script>
    $('.modal-content').resizable({
        minHeight: 300,
        minWidth: 300
    });
    $('.modal-dialog').draggable();
</script>
sachin
  • 1
  • 2