I have a simple vertically draggable div, containing a set of vertically adjacent 100%-width divs (a bit like a list). The container div sits within an overflow:hidden div which is acting like a viewport onto the draggable. What I'm trying to do is create the illusion of an endless list. The draggable starts off positioned so that the first couple of elements are above the top edge of the viewport.
When the draggable is dragged down, and the first item in the list is about to become visible, then I want to move the bottom item to the top of the draggable and shift the position of the draggable back up so that it looks like nothing has happened, but when they keep dragging then they won't hit the top of the draggable - it'll just keep going as if the list were a very simple carousel
The problem I'm having is that altering the position of the draggable mid-drag doesn't seem to have any effect. Monitoring the reported position of the draggable by logging ui.position.top on every call to the drag handler shows that it's as if the position change has been ignored - the pixel position just keeps going up as if nothing had happened. Moving the last item of the list up works fine, so it looks very odd.
I've stepped through and verified that, if I call $(event.target).css('top', '-200px') (for example) then the draggable does indeed shift up, but it seems to go right back after the drag handler has returned. I've tried modifying the value of top in ui.position, since a look at the source code suggests that the draggable widget respects any changes to that, but that doesn't seem to have any effect either.
If you stop the drag (by releasing the mouse) during the debugger step through then it all works perfectly.
Here's some sample code
- <!DOCTYPE html>
- <html lang='en'>
- <head>
- <script src="jquery-1.4.2.min.js" type="text/javascript"></script>
- <script src="jquery.ui.core.js" type="text/javascript"></script>
- <script src="jquery.ui.widget.js" type="text/javascript"></script>
- <script src="jquery.ui.mouse.js" type="text/javascript"></script>
- <script src="jquery.ui.draggable.js?1267439578" type="text/javascript"></script>
- <style type="text/css" media="screen">
- .viewport {
- width: 700px;
- height: 400px;
- border: 1px solid red;
- overflow: hidden;
- position: relative; }
- .viewport .surface {
- width: 2100px;
- position: absolute;
- left: -700px; }
- .viewport .surface .element {
- height: 98px;
- border: 1px solid black; }
- .viewport .surface .element p {
- width: 10%;
- margin: 0 auto; }
-
- #rolling-pin-vertical-carousel .surface {
- top: -200px; }
-
- </style>
-
- <script type="text/javascript" charset="utf-8">
- <![CDATA[
- var Testbed = {};
-
- Testbed.vertical_carousel = function(event, ui) {
- console.log(ui.position.top);
- if (ui.position.top > -100) {
- var surface = $(event.target);
- surface.find('.element').last().prependTo(surface);
- surface.css('top', (ui.position.top - 100) + 'px');
- ui.position.top = ui.position.top - 100;
- }
- }
-
- $(document).ready(function() {
- $('#rolling-pin-vertical-carousel .surface').draggable({
- axis: 'y',
- drag: Testbed.vertical_carousel
- });
- });
- ]]>
- </script>
- <link href="/stylesheets/testbed.css?1268643419" media="screen" rel="stylesheet" type="text/css" />
- </head>
- <body>
- <h1>The rolling pin - vertical carousel</h1>
- <div id='rolling-pin-vertical-carousel'>
- <div class='viewport'>
- <div class='surface'>
- <div class='element'>
- <p>1</p>
- </div>
- <div class='element'>
- <p>2</p>
- </div>
- <div class='element'>
- <p>3</p>
- </div>
- <div class='element'>
- <p>4</p>
- </div>
- <div class='element'>
- <p>5</p>
- </div>
- <div class='element'>
- <p>6</p>
- </div>
- </div>
- </div>
- </div>
- </body>
- </html>
Any ideas?
I'm using jQuery 1.4.2 and jQuery UI 1.8rc3
Thanks,
Matt