I'm currently trying to apply a containment to both the resize and the drag of a component. The drag accepts the containment bounds perfectly but the resize decides to break out and not follow the specified boundaries that I have set - anything i'm doing wrong here?
See the following jsFiddle (http://jsfiddle.net/cyVYq/30/);
$(".Event3").draggable({
axis: "x",
containment: "#2"
}).resizable({
axis: "x",
handles: "e, w",
containment: "#2"
})
Many Thanks,
You're trying to contain the resizable in an element that isn't its parent (#2)
Try setting the container to its parent .TimelineContainer:
$(".Event3").resizable({
axis: "x",
handles: "e, w",
containment: ".TimelineContainer"
})
Fiddle
Update:
From the JQuery-UI documentation it appears that the intended use of the containment option is to be used within the confines of a parent element. It doesn't seem possible to use this option the way you intend. Try something like:
$(".Event3").resizable({
axis: "x",
handles: "e, w",
containment: ".TimelineContainer",
resize: function(event, ui) {
// Define the dimensions of this element
var left = ui.position.left;
var width = ui.size.width;
var right = left + width;
// Define my constraints based on the element #2
var constraintLeft = $('#2').position().left;
var constraintWidth = $('#2').width();
var constraintRight = constraintLeft + constraintWidth;
// if resizable has gone further left than the constraint
if(left < constraintLeft) {
var left = parseInt($(this).css('left'));
// measure the difference between this left and the constraint left
var difference = constraintLeft - left;
// make up the difference
$(this).css('left', constraintLeft);
// make sure your width stays the same
$(this).width($(this).width() - difference);
// cancel the event
$(this).resizable('widget').trigger('mouseup');
}
// if resizable has gone further right than the constraint
if( right > constraintRight) {
// change the width to fit between the constraint right and this left
$(this).width(constraintRight - left);
// cancel the event
$(this).resizable('widget').trigger('mouseup');
}
}
});
Where you manually define the boundaries of the resizable and then you call a mouseup when the resizable has reached those boundaries. Here's the fiddle to play around with:
Fiddle
Related
I have a draggable element, which is also resizable and rotatable. These rotations are handled by CSS transformations, however, when an element is rotated, it makes the draggable feature spin out of control.
Heres a (updated) fiddle: Click me
What I think happens is that when an element is rotated, it's height and width obviously stay the same, just at an angle, however, jQuery doesn't account for the rotation, making it think that the element is in it's normal horizontal way, which results in the "bugg" shown in the fiddle above.
In a wild goose chase for the answer, I read somewhere that this would do the trick:
refreshPositions: true,
But it didn't work. Neither did destroying the draggable function on the element and then reinitiating it. Is there a way to fix this, so the containment will function normally, thus making jQuery recognise the rotation?
Thanks.
One option is to handle the containment yourself. Here is one possible way to do that.
I am using getBoundingClientRect to get the height and width of the rotated element. Using these values I can get an idea of where the dragged element resides in relation to it's parent container and force it to stay within those bounds.
var boundingContainer, boundingDraggable, prevLeft, prevTop;
$(".draggable").draggable({
classes: {
"ui-draggable-dragging": "highlight-draggable"
},
start: function(event, ui) {
boundingDraggable = ui.helper[0].getBoundingClientRect();
boundingContainer = ui.helper.closest('#draggableContainer')[0].getBoundingClientRect();
},
drag: function(event, ui) {
if(ui.offset.left <= boundingContainer.left){
if(ui.position.left < prevLeft){
ui.position.left = prevLeft;
}
}
if(ui.offset.top <= boundingContainer.top){
if(ui.position.top < prevTop){
ui.position.top = prevTop;
}
}
if(ui.offset.left+boundingDraggable.width >= boundingContainer.right){
if(ui.position.left > prevLeft){
ui.position.left = prevLeft;
}
}
if(ui.offset.top+boundingDraggable.height >= boundingContainer.bottom){
if(ui.position.top > prevTop){
ui.position.top = prevTop;
}
}
prevLeft = ui.position.left;
prevTop = ui.position.top;
}
});
Fiddle
jQuery UI draggable plugin allow you to set contain for draggable like
$('.panel').draggable({
handle: ".head",
containment: "parent",
cursor: "pointer"
}
);
My question is how can I detect if div have reached the edge of its containment?
I want to mimic the Windows effect when you drag a panel to edge it go 50% width and 100% height but I don't know how to detect/trigger an event when div reaches the edge.
Thanks
You can use the drag function to return the position of the draggable element while it's being moved. Compare that against the position of the outer edge of the parent and when the two intersect trigger the resizing action.
This fiddle is a very simplified version of what you're looking for, but it should illustrate the basic concept and get you started in the right direction. Hopefully this helps.
http://jsfiddle.net/98jpC/1/
$(function(){
var draggableRight;
var draggableWidth = $('.draggable').width();
var parentWidth = $('#parent').width();
$('.draggable').draggable({
containment: 'parent',
drag: function(e, ui){
draggableRight = ui.position.left + draggableWidth;
if(draggableRight == parentWidth){
$(document).trigger("mouseup");
$('.draggable').css({
width: '50%',
height: '100%',
top: 0,
left: '50%'
});
}
}
});
});
I am having an unusual issue with droppable. I have a lot of code so I will try to simplify my question as best as possible.
I have two divs that are droppable within a container (which is the size of the window).
div1 is 5000px by 5000px and is centered on the page (AKA there are offset positions of large numbers). div2 is absolutely positioned within the container on top of the first div. It's width is 100% of the container and height is about 50px.
I also have loads of drag and drop items that need to move from one div to the other, and back again.
The problem is, once I move an item from div2 into div1, they will not move back to div 2 again. they simply go underneath the div and remain in div1. I would love to post code, but there is so much I am not sure it would help.
I am currently using greedy:true on each drag and drop div.
Any ideas? Thanks in advance.
EDIT
This is the jquery for div2
$("#bs-quickAdd-que").droppable({
accept: ".bs-items",
drop: function( e, ui ){
var $this = ui.draggable; // the element being dragged
$this.addClass("bs-que-items item-in-que");
$("#bs-quickAdd-que").css({"background-color": "transparent"});
},
over: function( e, ui ){ // when drag of the que box
var $this = ui.draggable; // the elementbeing dragged
$this.appendTo("#bs-quickAdd-que").removeClass("item-in-grid");
$("#bs-quickAdd-que").css({"background-color": "#fff"});
},
out: function( e, ui ){
var $this = ui.draggable; // the element being dragged
$this.appendTo(elem).addClass("item-in-grid").removeClass("bs-que-items");
$("#bs-quickAdd-que").css({"background-color": "transparent"});
},
greedy: true
});
This is the jquery for div1
elem.droppable({
accept: ".bs-items",
greedy: true
});
Here is the items draggable
$(".bs-items").draggable({
containment: "window",
grid: [10,10],
stack: ".bs-items",
cursorAt: {top: 15, left: 10},
drag: function(e,ui){
var $this = ui.helper, $parent = $this.parent(); // the element being dragged
if($parent.is("#grid")){
thisx = Math.round(e.pageX - elem.offset().left);
thisy = Math.round(e.pageY - elem.offset().top);
}else{
thisx = Math.round(e.pageX - $("#bs-quickAdd-que").offset().left);
thisy = Math.round(e.pageY - $("#bs-quickAdd-que").offset().top);
}
ui.position.left = thisx-($this.width()/2);
ui.position.top = thisy-($this.height()/2);
}
});
Here's the thing.
jQuery UI prevents a ancestor droppables from receiving drop events when a descendent droppable is configured with {greedy: true}. It does not prevent sibling or cousin droppables from receiving drop events in cases where one overlaps the other.
This is a design decision by jQuery UI. They do not intend to fix it.
Edit#1:
Since I asked this problem, I made a script which allows the elements to move together, but with problems. :(
$(this).append(
$('<div class="elem '+classes+'" style="width: 210px; height: 30px" data-modby="'+ui.draggable.attr("data-for")+'"><p>'+text+'</p></div>')
.resizable({
grid: 10,
maxHeight: 120,
maxWidth: 600,
minHeight: 30,
minWidth: 210,
containment: ".box-section"
})
.draggable({
grid: [10,10],
containment: ".box-section",
scroll: false,
helper: "original",
start: function(event, ui) {
posTopArray = [];
posLeftArray = [];
if ($(this).hasClass("r-active")) {
$(".elem.r-active").each(function(i) {
thiscsstop = $(this).css('top');
if (thiscsstop == 'auto') thiscsstop = 0;
thiscssleft = $(this).css('left');
if (thiscssleft == 'auto') thiscssleft = 0;
posTopArray[i] = parseInt(thiscsstop);
posLeftArray[i] = parseInt(thiscssleft);
});
}
begintop = $(this).offset().top;
beginleft = $(this).offset().left;
},
drag: function(event, ui) {
var topdiff = $(this).offset().top - begintop;
var leftdiff = $(this).offset().left - beginleft;
if ($(this).hasClass("r-active")) {
$(".elem.r-active").each(function(i) {
$(this).css('top', posTopArray[i] + topdiff);
$(this).css('left', posLeftArray[i] + leftdiff);
});
}
}
})
);
The actual problem is the moved elements have to stay in the containment box (called .box-section and if I have a single element it works fine. Also if i have two elements has not the same width, if i pick the sorter one and drag, I can pull out the longer of the container.
Also, if I move them fast (like a ninja) they will slip, and they won't be in the same grid they used to be.
30 percent solved since:
I'm going to make a new thingy which can drag and drop items to a box, and resize them.
My problem is that, I can't make them move together. But with some rules.
Rule one: They must move based on a 10x10px grid.
Rule two: They can't move outside their frame.
(Resize is an issue which i simply can't imagine, so I don't care about it, resize will be later)
I made a fiddle for it here: http://jsfiddle.net/9fueY/ you can see this.
In the right side, you can see inputs and a and a checkbox (and on hover a button).
The checkbox is the draggable object, drag it to the image. Now you have some text or a star appeared on the left.
If you type anything to the inputs, it refreshes the text.
OnHover the right boxes you can see a button. By clicking on it, will make a clone of the first element. Drag it inside.
If you click to a right-side box, it will glow blue. Click to two boxes on the right, makes all the two textfields glow blue in the image.
Now this is the case when i want them to move together. :D
What's your opinion, what should I do with this?
Thank you very much. - Répás
There is a plugin i developed for dragging elements together. Please do use it if it makes sense.
https://github.com/someshwara/MultiDraggable
My page has several items (divs) that are draggable and resizable.
My code for doing this is given below:
part.draggable(
{
containment: 'parent',
drag: function(event, ui){
partIsDragging = true
part.prev().css('top', ui.position.top - 20 ).css('left', ui.position.left )
part.prev().show()
},
stop: function(event, ui) {
partIsDragging = false
}
}).resizable({
containment: 'parent',
handles: 'ne, se, sw, nw,n,w,e,s',
stop: function() {
}
});
The html structure for these is the following:
<body>
<div id="wrapper">
<div class="draggableItem"></div>
<div class="draggableItem"></div>
<div class="draggableItem"></div>
<div class="draggableItem"></div>
</div>
</body>
In my css files i have set body height: 100% and wrapper height: 100%. Width is always fixed for wrapper, width: 950px. I want my div to expand in height when the draggableItem reaches the bottom of the wrapper. Right now when the page is loaded, it has the height as big as the resolution allows it but in case I have more items in the wrapper then everything becomes cluttered and I would like when dragging an item to somehow expand the wrapper in height dynamically. This should happen only if I hit the bottom border.
PS: I am using jQuery and jQuery-ui.
I may have a solution. First off, I replaced part with '.draggableItem' and this where appropriate. Please tell me if that breaks the code in some critical way. In addition, I removed part.prev().css('top', ui.position.top - 20 ).css('left', ui.position.left ) in the code below.
function adjustWrapperHeight(movingObject)
{
var objectBottomPosition = $(movingObject).offset().top+$(movingObject).height()
var wrapperBottomPosition = $("#wrapper").offset().top+$("#wrapper").height()
if(wrapperBottomPosition-objectBottomPosition<distanceBuffer)
{
$("#wrapper").height($("#wrapper").height()+distanceBuffer+1)
}
}
var distanceBuffer = 20;
$('.draggableItem').draggable(
{
containment: 'parent',
drag: function(event, ui)
{
partIsDragging = true
adjustWrapperHeight(this)
},
stop: function(event, ui)
{
partIsDragging = false
}
}).resizable(
{
handles: 'ne, se, sw, nw,n,w,e,s',
resize: function(event, ui)
{
adjustWrapperHeight(this)
var objectRightPosition = $(this).offset().left+$(this).width()
var wrapperRightPosition = $("#wrapper").offset().left+$("#wrapper").width()
if(wrapperRightPosition<=objectRightPosition)
{
$(this).width(ui.originalSize.width)
var containmentLeftPosition = wrapperRightPosition-$(this).width()
$(this).offset({top:$(this).offset().top,left:containmentLeftPosition})
}
}
})
})
The function adjustWrapperHeight(movingObject) adjusts div#wrapper's height depending on a movingObject's bottom position. That is, when movingObject "pushes up" against div#wrapper's borders, it adjusts div#wrapper's height.
I had to use a hack for resizable. The containment: 'parent' for resizable (but not draggable) sets the containment to the container's ORIGINAL height or so it seems. That means as the height of div#wrapper dynamically changes, the constraint set by containment: 'parent' does not dynamically change. To fix this, I removed containment: 'parent' and indeed the entire containment and ensured that div#wrapper's right containment isn't broken within the resize event. Note that you should probably do this with div#wrapper's left containment as well.
Please tell me if this was helpful. Thank you.