6

After my lack of success with my previous post, I followed a suggestion and used Bootstrap's Dashboard example as a base, unfortunately with no success.

The aim is a page with a sidebar (col-md-3) that contains panels with all unsorted students (in small panels each), and a main area (col-md-9) that contains different groups (larger panels), in which the students can be dragged and dropped with JQeryUI Sortable. This screenshot shows the concept.

This works fine, except for one problem: while the sidebar does not have a horizontal scrollbar (even when selecting "overflow-x: auto"), it seems to become bigger when trying to drag a panel out from it. This screenshot at the moment when I am dragging the fourt panel from above shows the problem.

Here is a streamlined version of the code:

CSS:

<link href="/static/css/bootstrap.css" rel="stylesheet" media="screen">
<style type="text/css">
    body {
        padding-top: 60px;
        padding-bottom: 40px;
    }

    @media (min-width: 768px) {
      .sidebar {
        position: fixed;
        top: 51px;
        bottom: 0;
        left: 0;
        z-index: 1000;
        padding: 20px;
        overflow-y: auto;
      }
    }
</style>

HTML:

<div class="container">
    <div class="row">
        <div class="col-sm-4 col-md-3 sidebar">
            <div class="unsortedList panel panel-default">
                <div class="panel-heading">
                    Not assigned
                </div>
                <div class="panel-body">
                    <ul id="0" class="list-unstyled connectedLists">
                        <li class="panel panel-primary innerpanel" id="student_1_id">
                            <input type="hidden" name="student_1_id" value="0">
                            <div class="panel-body">
                                Student 1 Name
                            </div>
                        </li>
                        <li class="panel panel-primary innerpanel" id="student_2_id">
                            <input type="hidden" name="student_2_id" value="0">
                            <div class="panel-body">
                                Student 2 Name
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
        </div>

        <div class="col-sm-8 col-sm-offset-4 col-md-9 col-md-offset-3 main">
            <div class="col-md-4 col-sm-4 col-xs-5" id="panel_1">
                <div class="panel panel-default outerpanel">
                    <div class="panel-heading">
                        Group 1
                    </div>
                    <div class="panel-body">
                        <ul id="1" class="list-unstyled connectedLists">
                            <li class="panel panel-primary innerpanel" id="student_3_id">
                                <input type="hidden" name="student_3_id" value="1">
                                <div class="panel-body">
                                    Student 3 Name
                                </div>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
            <div class="col-md-4 col-sm-4 col-xs-5" id="panel_2">
                <div class="panel panel-default outerpanel">
                    <div class="panel-heading">
                        Group 2
                    </div>
                    <div class="panel-body">
                        <ul id="2" class="list-unstyled connectedLists">
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

The (functioning and simplified) Javascript code:

$(document).ready(function(){

    jQuery(function(event, ui) {
        $('.connectedLists').sortable({
            connectWith: ".connectedLists",
            stop: function(event, ui) {          
                item = ui.item;
                var newList = item.closest("ul");
                var group = newList.attr('id');
                var formField = item.find("input");
                formField.val(group);
            },
        });
    });
};

Is there a way I can stop the sidebar from expanding when dragging? Thanks for looking through this mess!

Community
  • 1
  • 1
Tobi
  • 351
  • 1
  • 2
  • 20
  • Could you also paste your panel javascript code? – AyB May 11 '14 at 12:18
  • 1
    Have added it now. The dragging, sorting and so on does work flawlessly though. Thanks for looking into it! – Tobi May 11 '14 at 12:29
  • 1
    `overflow-x: auto` indeed seems to be a problem, since it's `auto`, it creates the scroll bar when dragged, we could try to change the `z-index` to prevent that, but I'm just curious why do you need the `overflow` property anyway? Since you are already using the grids. – AyB May 11 '14 at 12:47
  • You are right - overflow-x:auto was only in there for testing purposes. I changed it in the code above to overflow-y:auto, as in the original example. This does not solve the problem, though. When I take overflow-y:auto out, the problem is gone, but I cannot scroll that sidebar anymore (which is essential). Is there another way to allow scrolling? – Tobi May 11 '14 at 13:22

1 Answers1

2

Ok, this is a tricky problem but there's a little bit of 'hack' that we can do. It's a simple method.

To summarize your issue, you need overflow-y:scroll in your container holding the draggable, while you keep overflow-x:hidden. But, when you drag, the element still spreads across the container like as if the overflow-x had no effect. So here's what we do:

1) We describe the overflow-y:scroll property on DOM:

$(document).ready(function(){
  $('.sidebar').css('overflow','scroll');
});

We can't put this directly on the CSS because we are going to be changing this value later and the CSS default property overrides it.

2)

$('.panel-body').mousedown(function(){
  $('.sidebar').css('overflow-y','');
}); 

This means, when we select a draggable element (while the mouse is still down), we will hide the vertical scroll, that means both overflow won't be true. This is the important part, we know that removing overflow-y totally solves the issue but we need a vertical scrollbar. So we hide it only when an element is selected.

3)

$('.panel-body').mouseup(function(){
  $('.sidebar').css('overflow-y','scroll');
});

Once we have placed the draggable element in the place we wanted it to be, we put our vertical-scrollbar back.

That's it, this may not be a smooth solution since it's only a workaround.

You can have a look at how it works here:

DEMO (updated)

AyB
  • 11,609
  • 4
  • 32
  • 47
  • 1
    Thanks a lot - this solves it! The only problem in this answer is that you wrote "overflow: scroll", which should be "overflow-y:scroll". It was correct in the the demo. Thanks again! – Tobi May 11 '14 at 16:35
  • Hello again, @ICanHasKittenz - unfortunately, there is still a problem with this solution that I didn't see the first time. You can reproduce the error by adding more students panels to the sidebar, scrolling down a bit and trying to grab someone further below. When the javascript removes the scroll bar, the sidebar will jump to the top, making the mouse cursor be far above the dragged object. – Tobi May 11 '14 at 18:06
  • @Tobi You're right. I made quite some changes now, specially that the `.sidebar` has `overflow:hidden` to make the vertical scroll position stay and using helper method we clone the dragged element (else it appears behind the other containers while dragged). Also fixed the bug of not being to drag on an empty group. Please have a look at the updated demo. – AyB May 12 '14 at 06:07