Drag and Drop Categorized Item List with jQuery and ASP.NET MVC – Part 1

Initial Layout and jQuery Setup

There are plenty of to-do lists out there where you can drag and drop to sort individual items, but I wanted to take it a step further and introduce categories. I wanted the categories containing the items to be sortable themselves, and not just within one column but several so it would maximize use of the web page layout’s width. The main use case I had in mind was for a grocery list, where type of food would be the categories. But it could be used for other things like a movie collection (genres as categories) or a sports league player roster (team names as categories).

This is part one in a series. In this post I’ll go through the initial layout and jQuery setup. In future posts I’ll go through the ASP.NET MVC setup in detail along with the database interaction.

For starters I kicked off an ASP.NET MVC project in Visual Studio 2008. I wanted a simple 4-column layout, so I added the CSS files from the excellent 960 Grid System and cleared out the existing Site.css file.

I’m using both jQuery and jQuery UI’s Sortable functionality, both of which can be referenced on Google’s CDN to reduce the page load time. I also added a new javascript file in the Scripts folder for custom functions.

With all these references the <head> section of the master page (/Views/Shared/Site.Master) now looks like this:

<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>

    <link href="../../Content/reset.css" rel="stylesheet" type="text/css" />
    <link href="../../Content/text.css" rel="stylesheet" type="text/css" />
    <link href="../../Content/960.css" rel="stylesheet" type="text/css" />
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js" type="text/javascript"></script>
    <script src="../../Scripts/Custom.js" type="text/javascript"></script>
</head>

Since we’re not going to delve into the ASP.NET MVC project structure for now, I created a new View simply called “Main” in the /Views/Shared folder, which in turn references the master page. This will contain all the content HTML for the time being. Before I started this blog post I called the categories sections, so bear with me on the terminology switch from here on out.

Using the 960 Grid System’s structure I laid out the 4 columns. For now I just added placeholders for two sections in the first column, and one section each under the 2nd and 4th columns. Here’s the layout in Main.aspx so far:

<div class="container_12">

    <div class="clear"></div>

    <div class="grid_12" id="headerText">
        <h4>Categorized List Demo</h4>
    </div>

    <div class="clear"></div>

    <div class="grid_3 listColumn" id="col_1">
        <div class="secBox">
            <div class="secHeader">
                <h2 class="secName">Vegetables</h2>
            </div>
        </div>
        <div class="secBox">
            <div class="secHeader">
                <h2 class="secName">Fruit</h2>
            </div>
        </div>
    </div>

    <div class="grid_3 listColumn" id="col_2">
        <div class="secBox">
            <div class="secHeader">
                <h2 class="secName">Meat</h2>
            </div>
        </div>
    </div>

    <div class="grid_3 listColumn" id="col_3">
    </div>

    <div class="grid_3 listColumn" id="col_4">
        <div class="secBox">
            <div class="secHeader">
                <h2 class="secName">Dairy</h2>
            </div>
        </div>
    </div>

    <div class="clear"></div>

</div>

Within each section I added 3 items in an unordered list. Each section now follows this pattern:

<div class="secBox">
    <div class="secHeader">
        <h2 class="secName">Vegetables</h2>
    </div>

    <div class="itemBox">
        <ul class="itemList">
            <li class="itemRow">
                <span class="itemName">Broccoli</span>
            </li>
            <li class="itemRow">
                <span class="itemName">Spinach</span>
            </li>
            <li class="itemRow">
                <span class="itemName">Zuchinni</span>
            </li>
        </ul>
    </div>
</div>

CSS markup was added for simple styling. Here’s a screenshot:

2009-06-18_initial_layout

To make sure the root of the site brings up the view “Main”, go to /Controllers/HomeController.cs and make sure the Index action returns this view.

public ActionResult Index()
{
    return View("Main");
}

Next up is coding the javascript to enable drag and drop on both the sections and items. When making the sortable() call, sections must use the connectWith attribute to link to the 4 different columns, and items must use the same attribute to link to different sections.

For sections, I also set a handle so the user is forced to use the header to drag the sections around. If this isn’t included, there would be a conflict when dragging items since they already exist within the sections. Dragging a section by it’s header is also common among popular personalized home page sites such as iGoogle and PageFlakes. Other than that there are just some visual attributes set (cursor, opacity, placeholder) along with containment so the user can’t scroll off the page dragging things around. Here’s the javascript so far:

$(document).ready(function()
{
    InitSectionSorting();
    InitItemSorting();
});

function InitSectionSorting()
{
    $(".listColumn").sortable(
    {
        connectWith: ".listColumn",
        containment: "document",
        cursor: "move",
        handle: ".secHeader",
        opacity: 0.8,
        placeholder: "secBoxPlaceholder"
    });
}

function InitItemSorting()
{
    $(".itemList").sortable(
    {
        connectWith: ".itemList",
        containment: "document",
        cursor: "move",
        opacity: 0.8,
        placeholder: "itemRowPlaceholder"
    });
}

Here’s what it looks like dragging a section:

2009-06-18_section_drag

…and an item:

2009-06-18_item_drag

That’s about it for the layout and sorting functionality. In future posts I’ll tackle adding, editing and deleting using jQuery’s AJAX calling ASP.NET MVC methods, which in turn access a SQL Server database.

Final note: The styling seems to get messed up in IE. Should look OK in FF, Chrome and Safari though.

Download the source code (requires Visual Studio 2008 and ASP.NET MVC 1.0)

Post to Twitter Post to Digg Post to Facebook

  • mtaylor1983
    I have a Div Container with Span elements inside that are draggable. Each element has a code and description because they are item numbers but for some reason when I drag them to another selection box they get truncated as soon as it hits a space so for example "Rat Roost" displays fine at first but when dragged and dropped it reads "Rat". Funny thing is when I save the data in SQL and init the page it displays the full name. Jquery must be doing something with that text value when its being dragged. Any ideas. mtaylor@arxistechnology.com and any help would be greatly appreciated
  • Might just be a CSS issue. I'd have to see the app running or at least the resulting html/javascript/css. Feel free to email it (pderksen@gmail.com).
  • roger
  • Thanks for pointing this out. It's been corrected. Much appreciated.
blog comments powered by Disqus