How do I set the containment on a jQuery UI Dialog?
Asked Answered
T

3

7

Is it possible to add containment (confining to the boundary of another element) to jQuery UI's Dialog?

Tadich answered 25/5, 2010 at 10:3 Comment(2)
By containment you mean....? I'm unclear on what you're after here, clarify a bit?Roughshod
Well I mean I want to specify the area where the dialog can be dragged. Now it can be dragged all over the browser window..Tadich
V
3

You could target the dialog box and apply a containment to it. Try this:

var container = $('.dialog-container'),
    dialog = $('.ui-dialog');
// get container top left corner locations
var cx1 = container.offset().left,
    cy1 = container.offset().top;
// get dialog size
var dw = dialog.outerWidth(),
    dh = dialog.outerHeight();
// get container bottom right location, then subtract the dialog size
var cx2 = container.width() + cx1 - dw,
    cy2 = container.height() + cy1 - dh;
dialog.draggable( "option", "containment", [cx1, cy1, cx2, cy2] );

Edit: I set up a demo for you.
Edit2: Changed to use dialog outerWidth & outerHeight

Valedictory answered 25/5, 2010 at 11:59 Comment(3)
The problem with this is if you resize the viewport then the functionality breaks...Leakage
@Lee: that's easily fixed, see my answer.Terse
Don't forget to set the containment for the resizable widget, too.Hoke
T
11

@Mottie's on the right track, but there's a simpler and better solution:

var container = $('.dialog-container'),
    dialog = $('.ui-dialog');
dialog.draggable( "option", "containment", container );

Unlike Mottie's solution, this will not break if the viewport resizes. I've forked the JSFiddle here.

Terse answered 9/4, 2013 at 6:21 Comment(3)
+1 This was helpful. Also, worth noting that the container need not be actually the parent of dialog element. It could be any element to which you want to restrict dialog's movement to.Ike
@Nikhil: yep, that's definitely worth mentioning. Thanks for adding that!Terse
You also need to set the containment for the resizable widget, or you'll still be able to cross the bounds when resizing.Hoke
H
5

@Mac's on the right track, but the solution is not complete. You must also set the containment of the dialog's Resizable widget. If you only set the Draggable, you'll get containment when you drag, but when you grab the edges and resize you'll still go out of bounds.

So you'll want to do this, assuming #mydialog is the element you initially created the dialog from, and #boundary is the element you wish to confine it to (by the way, the container parameter can also be a selector):

let ui = $('#mydialog').closest('.ui-dialog');       // get parent frame
ui.draggable('option', 'containment', '#boundary');  // <-- drag, but not resize
ui.resizable('option', 'containment', '#boundary');  // <-- don't forget!!!

Here's an example snippet, toggle the checkboxes to switch the corresponding widget's confinement between 'document' (the default), and '#area'. Then experiment both with dragging the dialog by its title bar, and resizing it by its edges. Note what happens when you only select "Confine drag":

// Create dialog from #win with mostly default options.
$('#win').dialog({
  width: 200,
  height: 150,
  position: { my: 'center', at: 'center', of: '#area' }
});

// When checkbox changed, update confinement settings.
$('#draggable, #resizable').change(function () {
  let d = $('#draggable').prop('checked');
  let r = $('#resizable').prop('checked');
  let ui = $('#win').closest('.ui-dialog');
  ui.draggable('option', 'containment', d ? '#area' : 'document');
  ui.resizable('option', 'containment', r ? '#area' : 'document');
});
#area {
  position: relative;
  left: 2ex;
  top: 2ex;
  width: 400px;
  height: 300px;
  border: 1px solid red;
}

#win {
  font-size: 10pt;
  display: flex;
  flex-direction: column;
}

label {
  display: flex;
  align-items: center;
}
<head>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
  <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
</head>

<body>
  <div>Example</div>
  <div id="area"></div>
  <div id="win" title="test">
    <label><input type="checkbox" id="draggable">Contain drag</label>
    <label><input type="checkbox" id="resizable">Contain resize</label>
  </div>
</body>
Hoke answered 7/6, 2017 at 0:31 Comment(0)
V
3

You could target the dialog box and apply a containment to it. Try this:

var container = $('.dialog-container'),
    dialog = $('.ui-dialog');
// get container top left corner locations
var cx1 = container.offset().left,
    cy1 = container.offset().top;
// get dialog size
var dw = dialog.outerWidth(),
    dh = dialog.outerHeight();
// get container bottom right location, then subtract the dialog size
var cx2 = container.width() + cx1 - dw,
    cy2 = container.height() + cy1 - dh;
dialog.draggable( "option", "containment", [cx1, cy1, cx2, cy2] );

Edit: I set up a demo for you.
Edit2: Changed to use dialog outerWidth & outerHeight

Valedictory answered 25/5, 2010 at 11:59 Comment(3)
The problem with this is if you resize the viewport then the functionality breaks...Leakage
@Lee: that's easily fixed, see my answer.Terse
Don't forget to set the containment for the resizable widget, too.Hoke

© 2022 - 2024 — McMap. All rights reserved.