jquerycssjquery-uijquery-ui-sortablejquery-slide-effects

Jquery: Sortable inside a slidetoggle div


I am building a new UI using jquery and I am having some trouble using .sortable inside a div that is displayed using slide toggle. Here is the HTML (MVC Razor):

<div style="float:left; width:200px; margin-right:5px" >
    <div class="FeaturesContainer">  
    <b>Project backlog</b><br /> 
        @foreach (var feature in Model.Managment.tasksByFeature)
        {
            if (feature.Value.Count != 0)
            { 
                <div class="FeatureContainer">
                    <div class="FeatureHeading" id="@feature.Key.id">
                         <div class="icon" style="float:right">
                            <img width="20" src="../../Content/images/down.png" />
                         </div>
                        <span class="FeatureTitle">@feature.Key.summary</span>      
                    </div>
                    <div class="Feature">
                        <ul class="drop">
                        @foreach (var task in feature.Value)
                            { 
                                <li class="taskItem">
                                    @Html.ActionLink(task.summary, "Task", new { proj = Model.Managment.project.Id, id = task.id })<br />
                                    Effort: @task.Effort
                                </li>
                            }
                        </ul>
                    </div> 
                </div>
            }
        }
    </div>
</div>

<div style="float:left; width:190px;">
    <div class="SprintContainer" id="@Model.Managment.sprint.Id">
        <b>Tasks for this sprint</b><br />
        <ul class="drop">
        @foreach (var task in Model.Managment.tasksInSprint)
        {
            <li class="taskItem">
                @Html.ActionLink(task.summary, "Task", new { proj = Model.Managment.project.Id, id = task.id })<br />
                Effort: @task.Effort
            </li>
        }
        </ul>
        Max Effort: @Model.Metrics.Velocity<br />
        Total Effort: @Model.Managment.tasksInSprint.Sum(i => i.Effort)
    </div>
</div>

And the revlevent CSS:

.drop 
    { 
        list-style-type: none; 
        margin: 0; 
        float: left; 
        margin-right: 5px; 
        background: #eee; 
        padding: 5px; 
        width: 158px;
        min-height:75px;
    }    

    .drop li 
    { 
        padding: 5px; 
        font-size: .9em; 
        width: 145px; 
        cursor:move;
    }   

    .highlight
    {
        border: 1px dashed #3E3E3E;
        height:50px;
        margin-bottom:2px;
    }

    .FeaturesContainer
    {
        background-color:#FFFFFF;
        border: 2px solid #3E3E3E;
        color:#FE7F00;
        padding:5px;
        -moz-border-radius: 4px;
        border-radius: 4px;
        margin:  0 0 10px 0;  
    }

    .SprintContainer
    {
        background-color:#FFFFFF;
        border: 2px solid #3E3E3E;
        color:#FE7F00;
        padding:5px;
        -moz-border-radius: 4px;
        border-radius: 4px;
        margin-bottom:10px;
        margin-right: 5px;  
    }

    .FeatureContainer
    {
        background-color:#BEBEBE;
        border: 1px solid #3E3E3E;
        color:#FE7F00;
        padding:5px;
        margin-bottom:10px;
        margin-top:5px;
        margin-right: 5px;  
    }

    .FeatureHeading
    { 
        padding: 5px 10px;
        cursor: pointer;
        position: relative;
        margin:1px;
        color:#FFFFFF;
        background-color:#006600;
        border-left: 1px solid #3E3E3E;
        border-right: 1px solid #3E3E3E;
        border-top: 1px solid #3E3E3E;
    }

    .Feature
    {
        padding:0;
        margin:0 0 0 0;
        position:relative;
        border-left: 1px solid #3E3E3E;
        border-right: 1px solid #3E3E3E;
        border-bottom: 1px solid #3E3E3E;

    }

And the jQuery:

$(function () {
    $("ul.drop").sortable({ connectWith: "ul", dropOnEmpty: true, placeholder: "highlight" });
});

$(document).ready(function () {
        var visible = true;
        $(".Feature").hide();

        $(".FeatureHeading").click(function () {
            $(this).next(".Feature").slideToggle(function () {
                visible = !visible;
                $(this).css({'height': 'auto'})
                if (visible) {
                    $('img', this).attr('src', '../../Content/images/down.png');
                }
                else {
                    $('img', this).attr('src', '../../Content/images/up.png');
                }

            });
        });
});

The problem is, when I click the FeatureHeading, the Feature slides down as expected, but as soon as the animation is complete it immediately collapses, yet the content of the Feature div is still visible. The list items are still draggable, and I can drop them in the Sprintcontainer.

If I add overflow:hidden to the Feature, the feature will display as desired, however as soon as I try to drag a list item to the SprintContainer the item seems to go behind the FeatureContainer and I can’t see it being dragged until I release the mouse over the sprint container, at which point the list item appears in the sprint container as expected.

Is it possible to have a sortable list inside a slidetoggle div?


Solution

  • While you are using overflow:hidden, try using 'appendTo: document.body'

    http://api.jqueryui.com/sortable/#option-appendTo

    It will resolve your issues for the item going behind FeatureContainer