Skip to main content

Search and Top Navigation

#5920 closed bug (notabug)

Opened August 10, 2010 06:39PM UTC

Closed August 10, 2010 06:48PM UTC

Last modified October 03, 2012 05:03PM UTC

oversize draggable

Reported by: rotkiw Owned by:
Priority: minor Milestone: 1.9.0
Component: ui.draggable Version: 1.8.4
Keywords: Cc:
Blocked by: Blocking:
Description

If the draggable is bigger than the holder, the draggable is just snap to the edges of the holder.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>draggable test</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/jquery-ui.min.js"></script>
<script type="text/javascript">
	$(document).ready(function() {
		$('#drag').draggable({
			containment: 'parent',
			//grid: [20, 20]
		});
	});
</script>
<style type="text/css">
#holder {
	width:200px;
	height: 200px;
	overflow:hidden;
	background-color:#CF0;
}
#drag {
	width:400px;
	height: 400px;
	overflow:hidden;
	background-color: #C00;
}
#content {
	width:390px;
	height:390px;
	margin: 5px;
	background-color:#09F;
}
</style>
</head>
<body>
<div id="holder">
  <div id="drag">
    <div id="content">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Curabitur enim. Nullam id ligula in nisl tincidunt feugiat. Curabitur eu magna porttitor ligula bibendum rhoncus. Etiam dignissim. Duis lobortis porta risus. Quisque velit metus, dignissim in, rhoncus at, congue quis, mi. Praesent vel lorem. Suspendisse ut dolor at justo tristique dapibus. Morbi erat mi, rutrum a, aliquam nec, mattis semper, leo. Maecenas blandit risus vitae quam. Vivamus ut odio. Pellentesque mollis arcu nec metus. Nullam bibendum scelerisque turpis. Aliquam erat volutpat.</div>
  </div>
</div>
</body>
</html>

solution:

	_generatePosition: function(event) {

		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
		var pageX = event.pageX;
		var pageY = event.pageY;
		var flagX = false;
		var flagY = false;

		/*
		 * - Position constraining -
		 * Constrain the position to a mix of grid, containment.
		 */
		
		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
			
			if(this.containment) {
				if (((this.containment[2] < 0) && (this.offset.click.left - event.pageX < this.containment[0])) || ((this.containment[2] >= 0) && (event.pageX - this.offset.click.left < this.containment[0]))) {
					pageX = this.containment[0] + this.offset.click.left;
					flagX = true; // Prevent jump at oversized draggable element (cursor offset > dragabble width - holder width)
				}
				if (((this.containment[3] < 0) && (this.offset.click.top - event.pageY < this.containment[1])) || ((this.containment[3] >= 0) && (event.pageY - this.offset.click.top < this.containment[1]))) {
					pageY = this.containment[1] + this.offset.click.top;
					flagY = true;
				}
				if ((!flagX && (Math.abs(event.pageX - this.offset.click.left) > Math.abs(this.containment[2]))) || ((this.containment[2] >= 0) && (event.pageX - this.offset.click.left > this.containment[2]))) pageX = this.containment[2] + this.offset.click.left;
				if ((!flagY && (Math.abs(event.pageY - this.offset.click.top) > Math.abs(this.containment[3]))) || ((this.containment[3] >= 0) && (event.pageY - this.offset.click.top > this.containment[3]))) pageY = this.containment[3] + this.offset.click.top;
			}
			
			if(o.grid) {
				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
				pageY = this.containment ? (!(Math.abs(top - this.offset.click.top) < this.containment[1] || top - this.offset.click.top > Math.abs(this.containment[3])) ? top : (!(Math.abs(top - this.offset.click.top) < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
				pageX = this.containment ? (!(Math.abs(left - this.offset.click.left) < this.containment[0] || left - this.offset.click.left > Math.abs(this.containment[2])) ? left : (!(Math.abs(left - this.offset.click.left) < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
			}

		}
		
		return {
			top: (
				pageY																// The absolute mouse position
				- this.offset.click.top													// Click offset (relative to the element)
				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
			),
			left: (
				pageX																// The absolute mouse position
				- this.offset.click.left												// Click offset (relative to the element)
				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
			)
		};

	},
Attachments (1)
Change History (7)

Changed August 10, 2010 06:48PM UTC by scottgonzalez comment:1

resolution: → invalid
status: newclosed

Containing a draggable inside something that's smaller than the draggable itself doesn't make sense.

Changed November 08, 2010 04:11PM UTC by krazedout comment:2

Hi there,

I don't agree with scott's comment - I'm currently encountering this problem as well where my draggable contents is larger than the container element. This happens because I'm creating something with a google maps effect where the user can drag a large div inside a smaller viewport.

I do hope that the jquery devs will consider opening this issue again because there are situations where the draggable element is larger than its parent container (E.g. with overflow:hidden). In the meantime, I'm currently using the Mapbox plugin to circumvent this issue.

Thanks!

Changed January 05, 2011 02:23AM UTC by Seuldieu comment:3

_comment0: I also disagree with Scott's shortsighted comment--one of the first practical uses that came to mind for draggable elements, was creating a click-and-drag window similar to google maps. Thanks Krazedout for the Mapbox reference, seeing as I will probably use that as well for now. \ \ +1 for addressing this ticket1294194260580111

I also disagree with Scott's shortsighted comment--one of the first practical uses that came to mind for draggable elements, was creating a click-and-drag window similar to google maps. Thanks Krazedout for the Mapbox reference, seeing as I will probably use that as well for now.

+1 for Jquery UI devs addressing this ticket in a future release...

Changed July 11, 2011 10:51PM UTC by bart comment:4

_comment0: I also disagree with Scott's comment. This seems like a big oversight for 'draggable'. If I have a place where I'm letting someone view a large image in a small area and I want them to be able to drag it around to see the whole image, then I need draggable to be able to support the dragging of a large element inside a small container. \ \ I think this would be solvable if instead of defining a container box, I would be defining min/max values for the top and left properties. Then I could say that the max left position is "0" (so that I would never be able to move the image towards the right past its left edge).1310424921779643

I also disagree with Scott's comment. This seems like a big oversight for 'draggable'. If I have a place where I'm letting someone view a large image in a small area and I want them to be able to drag it around to see the whole image, then I need draggable to be able to support the dragging of a large element inside a small container.

It's the same situation if you open an image in Photoshop, make its window smaller than the image, then use the hand tool to drag the image inside that window. The image is contained within that window.

I think this would be solvable if instead of defining a container box, I would be defining min/max values for the top and left properties. Then I could say that the max left position is "0" (so that I would never be able to move the image towards the right past its left edge).

Changed November 12, 2011 10:53PM UTC by janrenn comment:5

_comment0: Containment smaller than draggable really doesn't make sense. You are talking about "viewport" smaller than draggable. Create helper "containment" block, give this block width = (2 * draggable_width – viewport_width), the same with height and center this block relative to viewport. Then attach this helper block as "containment". It works OK for me. \ \ However, simplifying setting "min" and "max" coordinates directly via Draggable API properties, not using containment as proxy should be nice.1321138424898092
_comment1: → 1321139263038417
_comment2: Containment smaller than draggable really doesn't make sense. You are talking about "viewport" smaller than draggable. Create helper "containment" block, give this block width = (2 * draggable_width – viewport_width), the same with height and center this block relative to viewport. Then attach this helper block as "containment". It works OK for me. \ \ However, simplifying setting "min" and "max" coordinates directly via Draggable API properties, not using containment as proxy, should be nice.1321139291597124
_comment3: However, simplifying setting "min" and "max" coordinates directly via Draggable API properties, not using containment as proxy, should be nice.1321139327524677
_comment4: Containment smaller than draggable really doesn't make sense. You are talking about "viewport" smaller than draggable. Create helper "containment" block, give this block width = (2 * draggable_width – viewport_width), the same with height and center this block relative to viewport. Then attach this helper block as "containment". It works OK for me.1321139337443825
_comment5: However, simplifying setting "min" and "max" coordinates directly via Draggable API properties, not using containment as proxy should be nice.1321139375693223
_comment6: Containment smaller than draggable really doesn't make sense. You are talking about "viewport" smaller than draggable. Create helper "containment" block, give this block width = (2 * draggable_width – viewport_width), the same with height and center this block relative to viewport. Then attach this helper block as "containment". It works OK for me. \ \ However, simplifying setting "min" and "max" coordinates directly via Draggable API properties, not using containment as proxy should be nice.1321139424519665
_comment7: However, simplifying setting "min" and "max" coordinates directly via Draggable API properties, not using containment as proxy should be nice.1321139501269818

Containment smaller than draggable really doesn't make sense. You are talking about "viewport" smaller than draggable. Create helper "containment" block, give this block width = (2 * draggable_width – viewport_width), the same with height, and center this block relative to viewport. Then attach this helper block as "containment". It works OK for me.

However, simplifying setting "min" and "max" coordinates directly via Draggable API properties, not using containment as proxy should be nice.

Changed November 12, 2011 10:53PM UTC by janrenn comment:6

Containment smaller than draggable really doesn't make sense. You are talking about "viewport" smaller than draggable. Create helper "containment" block, give this block width = (2 * draggable_width – viewport_width), the same with height and center this block relative to viewport. Then attach this helper block as "containment". It works OK for me.

However, simplifying setting "min" and "max" coordinates directly via Draggable API properties, not using containment as proxy should be nice.

Changed October 03, 2012 05:03PM UTC by scottgonzalez comment:7

milestone: 1.next1.9.0