Is it possible to add containment (con开发者_C百科fining to the boundary of another element) to jQuery UI's Dialog?
@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.
@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>
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
精彩评论