I have a draggable element that has containment set as parent. This works great but the div content can change making it taller. Is there anyway to trigger the drag event that will ensure it doesnt move from inside its parent. As right now it can overlap the parent until it is dragged then the containment kicks in.
Best Regards Mark
I've implemented a small plugin that does what you want. It can enforce the containment after the draggable changes size and it even works while you're in the middle of a drag. I've tested it with jQuery UI 1.8.6 and jQuery 1.4.3 but it might break with past or future releases since it has to use internal methods.
http://jsbin.com/uvino4/27
/*
* jQuery UI RefreshContainment v0.1
*
* A plugin for jQuery UI's Draggable. It adds a refreshContainment method to
* every draggable which allows you to use the containment option on draggables
* with dynamically changing sizes.
*
* Depends:
* jquery.ui.core.js
* jquery.ui.widget.js
* jquery.ui.mouse.js
* jquery.ui.draggable.js
*/
(function ($){
var $window = $(window);
// We need to know the location of the mouse so that we can use it to
// refresh the containment at any time.
$window.data("refreshContainment", {mousePosition: {pageX: 0, pageY: 0}});
$window.mousemove(function (event) {
$window.data("refreshContainment", {
mousePosition: {pageX: event.pageX, pageY: event.pageY}
});
});
// Extend draggable with the proxy pattern.
var proxied = $.fn.draggable;
$.fn.draggable = (function (method){
if (method === "refreshContainment") {
this.each(function (){
var inst = $(this).data("draggable");
// Check if the draggable is already being dragged.
var isDragging = inst.helper && inst.helper.is(".ui-draggable-dragging");
// We are going to use the existing _mouseStart method to take care of
// refreshing the containtment but, since we don't actually intend to
// emulate a true _mouseStart, we have to avoid any extraneous
// operations like the drag/drop manager and event triggering.
// So we save the original member values and replace them with dummies.
var ddmanager = $.ui.ddmanager;
$.ui.ddmanager = null;
var trigger = inst._trigger;
inst._trigger = function () { return true; }
var mousePosition = $window.data("refreshContainment").mousePosition;
var fakeEvent = {
pageX: mousePosition.pageX, pageY: mousePosition.pageY
};
inst._mouseStart(fakeEvent);
// Return those extraneous members back to the original values.
inst._trigger = trigger;
$.ui.ddmanager = ddmanager;
// Clear the drag, unless it was already being dragged.
if (!isDragging) {
inst._clear();
}
});
return this;
}
else {
// Delegate all other calls to the actual draggable implemenation.
return proxied.apply(this, arguments);
}
});
})(jQuery);
<!DOCTYPE html>
<html>
<head>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
<style>
#container { width: 20em; height: 20em; border: 0.5em solid black; }
.draggable { width: 5em; height: 5em; border: 0.2em solid black; position: absolute; }
#one { background-color: #F55; }
#two { background-color: #5F5; }
</style>
</head>
<body>
<div id="container">
<div class="draggable" id="one">drag me</div>
<div class="draggable" id="two">drag me</div>
</div>
</body>
</html>
var draggables = $('.draggable');
draggables.draggable({containment: 'parent', stack: draggables});
var resizeDraggables = function (){
draggables.
each(function (){
var size = 5 + Math.random() * 5;
size = size.toString() + "em";
$(this).css({width: size, height: size});
}).
draggable("refreshContainment");
};
resizeDraggables();
setInterval(resizeDraggables, 2000);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With