I have two elements:
1. A parent of fixed height, overflow:hidden
2. Its child, of larger fixed height.
You don't have to drag anything for that kind of structure. What you need is to set up the parent div with overflow-x:hidden; and overflow-y:scroll;. That way, its content will be scrollable.
If you want to hide the scrollbar, just put this property: .dragPanel::-webkit-scrollbar{width:0 !important} and that's it! I don't really know why you were thinking of dragging elements instead of just scrolling the content (which is the correct way to carry out this kind of "problems"). Anyways, I hope it helps anybody who needs to fit the same necesity. Greetings!
I had the same problems and the answers didn't help me. Some javascript later I think the following is a better solution.
(Anybody knows how to turn this into a jQuery plugin?)
<!DOCTYPE html>
<html>
<head>
<title>Draggable limited to the container</title>
<style type="text/css">
#container {
cursor: move;
overflow: hidden;
width: 300px;
height: 300px;
border: 1px solid black;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
<script type="text/javascript">
$(function() {
$.globalVars = {
originalTop: 0,
originalLeft: 0,
maxHeight: $("#draggable").height() - $("#container").height(),
maxWidth: $("#draggable").width() - $("#container").width()
};
$("#draggable").draggable({
start: function(event, ui) {
if (ui.position != undefined) {
$.globalVars.originalTop = ui.position.top;
$.globalVars.originalLeft = ui.position.left;
}
},
drag: function(event, ui) {
var newTop = ui.position.top;
var newLeft = ui.position.left;
if (ui.position.top < 0 && ui.position.top * -1 > $.globalVars.maxHeight) {
newTop = $.globalVars.maxHeight * -1;
}
if (ui.position.top > 0) {
newTop = 0;
}
if (ui.position.left < 0 && ui.position.left * -1 > $.globalVars.maxWidth) {
newLeft = $.globalVars.maxWidth * -1;
}
if (ui.position.left > 0) {
newLeft = 0;
}
ui.position.top = newTop;
ui.position.left = newLeft;
}
});
});
</script>
</head>
<body>
<div id="container">
<img id="draggable" src="avatar.jpg" />
</div>
</body>
</html>
Ok,
Here is the route I have gone down...
When the page is loaded, I add a container div around the draggable list. I set it's height to twice that of the list, then position it up the page a little:
<script type="text/javascript">
$(document).ready(function() {
CreateContainerDiv();
$('.dragPanel').addClass("hover");
$('.myList').draggable({ axis: 'y', containment: 'parent' });
});
function CreateContainerDiv() {
var dragPanel = $('.dragPanel');
var dragTarget = $('.myList');
// add the container panel
var newPanelHeight = dragTarget.outerHeight() * 2 - dragPanel.outerHeight();
dragTarget.wrap(document.createElement("div"));
// set its height and put it in the right place
dragTarget.parent().css("height", newPanelHeight);
dragTarget.parent().css("position", "relative");
var newPanelPosition = ((dragTarget.outerHeight() * -1) / 2);
dragTarget.parent().css("top", newPanelPosition);
}
</script>
The list is then contained to this new element.
This appears to do the job, but the positioning is all a little shakey if the list has any padding / margin applied. Any thoughts on that would be appreicated!
------Edit ---------
Ok, I think I have solved the placement issue. I have turned this into a plugin so other people don't have to spend time creating this functionality.
jQuery Drag-gable List at Github
Use the containment option:
$('.myList').draggable({
axis: 'y',
containment: 'parent'
});