Bootstrap 3 - drag element horizontal with vertica

2019-06-19 00:27发布

问题:

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!

回答1:

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)