Wednesday, December 08, 2010

ASP.NET MVC Master-Detail List view with a LINQ twist


The source code for this blog posting can be downloaded from this link. MasterDetailsWithALinqTwist.zip

I was asked the following question:


"I agree with that person that told you that is difficult to find a good sample for Master Detail views, in particular for people who are begining with ASP.NET MVC 2.
Your post is a quit good intent to help people like me, but I think it's a little complicated for beginners.

I try to find in Google and in specialized books an answer to a simple but, I think, a very usual problem. I'll explain it with an example:

3 files:

1- Books:
with BookID (int, key), BookTitle (string)

2- Authors:
with AuthorId (int, key), AuthorName (string)

3- AuthorBook
with AuthorId, BookId

The last file is a "junction file". We need it because a book has one or more auhtors.

The problem, which solution I can't find it anywhere, is how can I make a list with the book title with its authors, but not repeating the book title.

Thank you for your time,"

This question was posted as a comment on my blog posting ASP MVC 2.0 - Master Detail Views

First I would like to point out that normally in Object Relational Mapping on the OO side you normally do not create objects for the one-many or many-many relations present in the database - unless the relations themselves carry special data or they have special properties and thus can be promoted to "real" objects/classes.

This means that I will ignore the third file mentioned above in the question (3- AuthorBook with AuthorId, BookId).

So I tend to see the above as a Book class with a property IList Authors, like below

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication2.Models
{
 public class Book
 {
  public string Id { get; set; }
  public string Name { get; set; }
  public IList<Author> Authors { get; set; }
 }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MvcApplication2.Models
{
 public class Author
 {
  public string Id { get; set; }
  public string Name { get; set; }
 }
}

For this small sample code I did not bother to wire the code to a database but just created a LibraryRepository class that can be seen below, this class acts as a placeholder for a database.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication2.Models
{
 public class LibraryRepository
 {
  public IList<Book> GetBooks()
  {
   List<Book> books = new List<Book>() 
   {
    new Book() 
    {
     Id = "1",
     Name = "My First Book",
     Authors = new List<Author>() 
     {
      new Author() { Id = "A1", Name = "Author1" },
      new Author() { Id = "A2", Name = "Author2" }
     }
    },
    new Book() 
    {
     Id = "2",
     Name = "My Second Book",
     Authors = new List<Author> () 
     {
      new Author() { Id = "A3", Name = "Author3" },
      new Author() { Id = "A4", Name = "Author4" }
     }
    }
   };
   return books;
  }
 }
}

Now that we have the "database" and the models in place then we need the controller and the view. Ideally the LibraryRepository should be injected in to the controllers constructor using Dependency Injection (which I am not doing here).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication2.Models;

namespace MvcApplication2.Controllers
{
 [HandleError]
 public class HomeController : Controller
 {
  public ActionResult Index()
  {
   // Should be passed in via IOC and contructor injection
   LibraryRepository libraryRepository = new LibraryRepository();
   ViewData.Model = libraryRepository.GetBooks();
   return View();
  }
 }
}

And finally the strongly typed view that uses a nifty LINQ expression to aggregate the Authors into a single string for display purposes.

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcApplication2.Models.Book>>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
 Index
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Index</h2>

    <table>
        <tr>
            <th></th>
            <th>
                Id
            </th>
            <th>
                Name
            </th>
            <th>
                Authors
            </th>
        </tr>

    <% foreach (var item in Model) { %>
    
        <tr>
            <td>
                <%: Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) %> |
                <%: Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ })%> |
                <%: Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })%>
            </td>
            <td>
                <%: item.Id %>
            </td>
            <td>
                <%: item.Name %>
            </td>
            <td>
                <%: item.Authors.Select(author => author.Name).Aggregate((currentAuthorName, nextAuthorName) => currentAuthorName + ", " + nextAuthorName) %>
            </td>
        </tr>
    
    <% } %>

    </table>

    <p>
        <%: Html.ActionLink("Create New", "Create") %>
    </p>

</asp:Content>

1. Select the names from the Author object into an anonymous object of type
System.Linq.Enumerable.WhereSelectListIterator<MvcApplication2.Models.Author,string>

2. Aggregate the names in the anonymous object (System.Linq.Enumerable.WhereSelectListIterator<MvcApplication2.Models.Author,string>) adding a comma between.

The output ends up like the following.



The MVC design pattern argues that the views should be pretty lightweight and should only deal with presenting data, logic related to readying data for display / and actual formatting of data should ideally be located in the controller ( I am not doing that here ).

Saturday, December 04, 2010

Refactoring ASP MVC 2 to use Dependecy Injection (part2)


This is a continuation of my previous post Refactoring ASP MVC 2 to use Dependecy Injection (part1)

The main layers I would like in my application are the following


LayerContainsDepends on/using
GuiLayer(partial) views, user controls, jsPresentationLayer, (DomainLayer)
PresentationLayerviewmodels, controllers, MVC plumbingDomainLayer
DomainLayerdomain objects, business logicnothing
DataLayerLINQ generated classes, repository handlers ...DomainLayer

When we look at the dependencies it is worth noting that the DomainLayer does not depend on anything. The DomainLayer contains all our domain logic and relevant objects and we want to be able to swap the GUILayer but also the DataLayer (see more Domain-driven design @ Wikipedia)

Let us have a look at the domain model I have defined.


For clarity I have omitted several other classes. Since both the domain model and the database was created from the actual scenario we are trying to solve here they are remarkably similar, however this is not a requirement (it just makes the DB-OO mapping easier).

Since the PresentationLayer contains view models that are relevant to the way we present our data we might find that we have several view models for one domain model or one view model that is composed by more than one domain model. We do not want the domain models to know about the view models since they might change depending on a rich client GUI that allows more data to be shown, but then again they might not, the key point is that we do not know and neither does the DomainLayer.

To this effect I have added an interface that is used in the PresentationLayer (view models).
Please see sample implementations for the 3 view models.


using System;
using System.Collections.Generic;

namespace ReverseAuction.Models
{
    interface IDomainModelToViewModelConverter<T, U>
    {
        U ConvertDomainModelToViewModel(T domainEntity);
        List<U> ConvertDomainModelToViewModel(List<T> domainEntities);
    }
}

The reason for letting the ViewModels handle the conversion from DomainModel to ViewModel (this also goes for the data layer - the DataModels handle the conversion from DataModel to DomainModel) is that the domain model is the interface all other layer know about.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Appinux.ReverseAuction.Domain;

namespace Appinux.ReverseAuction.Models
{
    public class SimpleUserViewModel : IDomainModelToViewModelConverter<User, SimpleUserViewModel>
    {
        public string Username { get; set; }
        public Guid ID { get; set; }

        public SimpleUserViewModel ConvertDomainModelToViewModel(User domainEntity)
        {
            this.ID = domainEntity.ID;
            this.Username = domainEntity.Username;
            return this;
        }


        public List<SimpleUserViewModel> ConvertDomainModelToViewModel(List<User> domainEntities)
        {
            List<SimpleUserViewModel> viewModelList = new List<SimpleUserViewModel>();

            foreach (User domainEntity in domainEntities)
            {
                viewModelList.Add(new SimpleUserViewModel().ConvertDomainModelToViewModel(domainEntity));
            }
            return viewModelList;
        }
    }
}

More of the same here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Appinux.ReverseAuction.Domain;

namespace Appinux.ReverseAuction.Models
{
    public class ProjectBidViewModel : IDomainModelToViewModelConverter<ProjectBid, ProjectBidViewModel>
    {
        public SimpleUserViewModel Bidder { get; set; }
        public Double BidAmount { get; set; }
        public DateTime BidDate { get; set; }

        public ProjectBidViewModel ConvertDomainModelToViewModel(ProjectBid domainEntity)
        {
            this.BidAmount = domainEntity.Amount;
            this.BidDate = domainEntity.PostedDate;
            this.Bidder = new SimpleUserViewModel().ConvertDomainModelToViewModel(domainEntity.PostedBy);
            return this;
        }


        public List<ProjectBidViewModel> ConvertDomainModelToViewModel(List<ProjectBid> domainEntities)
        {
            List<ProjectBidViewModel> viewModelList = new List<ProjectBidViewModel>();

            foreach (ProjectBid domainEntity in domainEntities)
            {
                viewModelList.Add(new ProjectBidViewModel().ConvertDomainModelToViewModel(domainEntity));
            }
            return viewModelList;
        }
    }
}

and the last class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Appinux.ReverseAuction.Domain;

namespace Appinux.ReverseAuction.Models
{
    public class ProjectViewModel : IDomainModelToViewModelConverter<Project, ProjectViewModel>
    {
        public string Name { get; set; }
        public string Description { get; set; }
        public SimpleUserViewModel Owner { get; set; }
        public DateTime BiddingStartDate { get; set; }
        public DateTime BiddingEndDate { get; set; }
        public DateTime ProjectLauchDate { get; set; }
        public DateTime ProjectDeadline { get; set; }
        public double MaxAllowedBid { get; set; }
        public string Status { get; set; }
        public List<projectbidviewmodel> ProjectBids { get; set; }

        public ProjectViewModel ConvertDomainModelToViewModel(Project domainEntity)
        {
            this.Name = domainEntity.Name;
            this.Description = domainEntity.Description;
            this.Owner = new SimpleUserViewModel().ConvertDomainModelToViewModel(domainEntity.Owner);
            this.BiddingStartDate = domainEntity.BiddingStartDate;
            this.BiddingEndDate = domainEntity.BiddingEndDate;
            this.ProjectLauchDate = domainEntity.StartDate;
            this.ProjectDeadline = domainEntity.Deadline;
            this.MaxAllowedBid = domainEntity.MaxBidAmount;
            this.Status = domainEntity.Status.Name;
            this.ProjectBids = new ProjectBidViewModel().ConvertDomainModelToViewModel(domainEntity.Bids);
            
            return this;
        }


        public List<ProjectViewModel> ConvertDomainModelToViewModel(List<Project> domainEntities)
        {
            List<ProjectViewModel> viewModelList = new List<ProjectViewModel>();

            foreach (Project domainEntity in domainEntities)
            {
                viewModelList.Add(new ProjectViewModel().ConvertDomainModelToViewModel(domainEntity));
            }
            return viewModelList;
        }
    }
}

I have on purpose done a non optimal structuring of the code above. Before continuing have a look at Single responsibility principle.

The problem:
According to the Single responsibility principle a class should have one responsibility. This is always up to interpretation what is the specific class's responsibility. However since ViewModels per definition are responsible for carrying data from the controller to the View in ASP.NET MVC, they should not know about conversion between DomainModels and themselves.

Depending on the complexity of the mapping between ViewModels and DomainModels & DomainModels and DataModels Factory classes could improve the modularity and adherence to the Single responsibility principle.

So lets fix this.

We are going to split each of the ViewModels into a ViewModel containing the DTO / POCO and a static Factory class.

Now the classes look like the following:

using System;

namespace Appinux.ReverseAuction.Models
{
 public class SimpleUserViewModel
 {
  public string Username { get; set; }
  public Guid ID { get; set; }
 }
}

using System;
using System.Collections.Generic;
using Appinux.ReverseAuction.Domain;

namespace Appinux.ReverseAuction.Models
{
 public static class SimpleUserViewModelFactory
 {
  public static SimpleUserViewModel Create(User domainEntity)
  {
   SimpleUserViewModel viewModel = new SimpleUserViewModel();
   viewModel.ID = domainEntity.ID;
   viewModel.Username = domainEntity.Username;
   return viewModel;
  }

  public static List<SimpleUserViewModel> Create(List<User> domainEntities)
  {
   List<SimpleUserViewModel> viewModelList = new List<SimpleUserViewModel>();
   foreach (User domainEntity in domainEntities)
   {
    viewModelList.Add(SimpleUserViewModelFactory.Create(domainEntity));
   }
   return viewModelList;
  }
 }
}

using System;

namespace Appinux.ReverseAuction.Models
{
 public class ProjectBidViewModel
 {
  public SimpleUserViewModel Bidder { get; set; }
  public Double BidAmount { get; set; }
  public DateTime BidDate { get; set; }
 }
}

using System;
using System.Collections.Generic;
using Appinux.ReverseAuction.Domain;

namespace Appinux.ReverseAuction.Models
{
 public static class ProjectBidViewModelFactory
 {
  public static ProjectBidViewModel Create(ProjectBid domainEntity)
  {
   ProjectBidViewModel viewModel = new ProjectBidViewModel();
   viewModel.BidAmount = domainEntity.Amount;
   viewModel.BidDate = domainEntity.PostedDate;
   viewModel.Bidder = SimpleUserViewModelFactory.Create(domainEntity.PostedBy);
   return viewModel;
  }

  public static List<ProjectBidViewModel> Create(List<ProjectBid> domainEntities)
  {
   List<ProjectBidViewModel> viewModelList = new List<ProjectBidViewModel>();
   foreach (ProjectBid domainEntity in domainEntities)
   {
    viewModelList.Add(ProjectBidViewModelFactory.Create(domainEntity));
   }
   return viewModelList;
  }
 }
}

using System;
using System.Collections.Generic;

namespace Appinux.ReverseAuction.Models
{
 public class ProjectViewModel
 {
  public string Name { get; set; }
  public string Description { get; set; }
  public SimpleUserViewModel Owner { get; set; }
  public DateTime BiddingStartDate { get; set; }
  public DateTime BiddingEndDate { get; set; }
  public DateTime ProjectLauchDate { get; set; }
  public DateTime ProjectDeadline { get; set; }
  public double MaxAllowedBid { get; set; }
  public string Status { get; set; }
  public List<ProjectBidViewModel> ProjectBids { get; set; }
 }
}

using System;
using System.Collections.Generic;
using Appinux.ReverseAuction.Domain;

namespace Appinux.ReverseAuction.Models
{
 public static class ProjectViewModelFactory
 {
  public static ProjectViewModel Create(Project domainEntity)
  {
   ProjectViewModel viewModel = new ProjectViewModel();
   viewModel.Name = domainEntity.Name;
   viewModel.Description = domainEntity.Description;
   viewModel.Owner = SimpleUserViewModelFactory.Create(domainEntity.Owner);
   viewModel.BiddingStartDate = domainEntity.BiddingStartDate;
   viewModel.BiddingEndDate = domainEntity.BiddingEndDate;
   viewModel.ProjectLauchDate = domainEntity.StartDate;
   viewModel.ProjectDeadline = domainEntity.Deadline;
   viewModel.MaxAllowedBid = domainEntity.MaxBidAmount;
   viewModel.Status = domainEntity.Status.Name;
   viewModel.ProjectBids = ProjectBidViewModelFactory.Create(domainEntity.Bids);
   return viewModel;
  }

  public static List<ProjectViewModel> Create(List<Project> domainEntities)
  {
   List<ProjectViewModel> viewModelList = new List<ProjectViewModel>();
   foreach (Project domainEntity in domainEntities)
   {
    viewModelList.Add(ProjectViewModelFactory.Create(domainEntity));
   }
   return viewModelList;
  }
 }
}

Let us look at how the traditional layering of tiered applications often look like.


Now lets look at how the same application usually looks like after a few iterations of feature additions based on new requirements from the business.
The technical debt increases, and a normal consequence is that the number of dependencies increase.



My proposal to let the entire stack of layers revolve around the domain layer means that the presentation layer does not have any indirect dependecy on anything else than the DomainLayer. The same goes for the DataLayer. This is actually how it works in most businesses, the business requirements are the driving factor for development and IMHO from a development standpoint the application should have the DomainLayer as the driver (since the DomainLayer should be the software equivalent of the buisiness requirements) (I know this is not the full story since there
often also are UI requirements etc ... but let us for now, arrogantly :), ignore these.

The picture below shows the dependencies in the approach I am suggesting here.



The whole point about interface based design is that you can swap classes with other classes that implement the same interface.

However if you new up specific classes in methods then you are adding a hard dependecy on the class. The code below show how a lot of code looks. This is a contrived example in real life applications it is never one single new statement but many all over the place. The classes needed to implement functionality often resides in several assemblies / namespaces. This means that you very quicly get into dependecy hell.

And on a side note it makes Test Driven Development much more difficult since you cannot mock the dependecies.

using System;
using System.Web.Mvc;
using SomeApplication.Domain;

namespace SomeApplication.Domain
{
 public interface ISomeInterface 
 {
  string DoSomething();
 }

 public class SomeClass : ISomeInterface
 {
  public string DoSomething()
  {
   throw new NotImplementedException();
  }
 }

}

namespace SomeApplication.Presentation
{
 public class HomeController : Controller
 {
  public HomeController()
  { 
  }
  
  public ActionResult Index()
  {
   // Bad Bad Bad - this is adding a dependency directly to the SomeApplication.Domain.SomeClass
   ISomeInterface someInteface = new SomeClass();
   return View();
  }
 }
}

Let us try to take away the knowledge about what specific class that is being used in the controller in the sample above.

using System;
using System.Web.Mvc;
using SomeApplication.Domain;

namespace SomeApplication.Domain
{
 public interface ISomeInterface 
 {
  string DoSomething();
 }

 public class SomeClass : ISomeInterface
 {
  public string DoSomething()
  {
   throw new NotImplementedException();
  }
 }

}

namespace SomeApplication.Presentation
{
 public class HomeController : Controller
 {
  private ISomeInterface someInterface;
  public HomeController(ISomeInterface someInterface)
  { 
   this.someInterface = someInterface;
  }
  
  public ActionResult Index()
  {
   // Now this class knows nothing about the concrete class, this knowledge is pushed higher up the call stack
   someIterface.DoSomething();
   return View();
  }
 }
}

The above way of structuring code is called constructor injection. In addition there are property injection and method injection. This is not really anything new. Since the advent of OO interface based design this approach have been recommended, but now this specific way of coding OO have a name Dependency injection.

The highest point in the call stack with regards to Dependency Injection is normally called the Composition Root. Composition Root is normally located as close to the application start as possible, so for an ASP.NET application this would normally be the Global.asax.

That the subject of the next post in this series. How to manually implement Dependency Injection in ASP.NET MVC.

Thursday, December 02, 2010

SHIFT Click javascript selection

I found myself needing a standard shift click selection functionality JavaScript for a website.  Preferably it should encapsulate the actual SHIFT click logic so it would be easy to use and reuse. It should provide the same or similar functionality of windows explorer or Konqueror. I was not able to find anything that I felt suited my need so I rolled my own. It is based on JQuery. You can see a demo of the Shift Click Javascript selection here.

I have tested it in Firefox 3.6, Chrome5/6 and IE8.

First the accompanying index.html page

<html>
<head>
<link href="style.css" rel="Stylesheet" type="text/css">
<title></title>
</head>
<body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="ShiftClick.js" type="text/javascript" charset="utf-8"></script>
<script src="main.js" type="text/javascript" charset="utf-8"></script>
<ul id="my-list">
    <li data-id="1">
        <div class="checkbox"></div>
        <h4 title="My name" class="name">My item1</h4>
    </li>
    <li data-id="2">
        <div class="checkbox"></div>
        <h4 title="My name" class="name">My item2</h4>
    </li>
    <li data-id="3">
        <div class="checkbox"></div>
        <h4 title="My name" class="name">My item3</h4>
    </li>
    <li data-id="4">
        <div class="checkbox"></div>
        <h4 title="My name" class="name">My item4</h4>
    </li>
    <li data-id="5">
        <div class="checkbox"></div>
        <h4 title="My name" class="name">My item5</h4>
    </li>
</ul>
</body>
</html>

and now the style.css file

#my-list li { height: 16px; position: relative; cursor: pointer; margin: 10px 0;}

#my-list li div, 
#my-list li h4 { position: absolute; overflow: hidden; left: 5px; margin: 0; top: 0;}

#my-list li div.checkbox { border-style:solid; border-width:1px; border-color:#fff; cursor: pointer; left: -25px; height: 17px; width: 17px; background: url(check-mark.png) no-repeat 0 0;}
#my-list li.checked div.checkbox { background-position: -16px 0; }

the main.js file

/**
* Solution specific file that is using the ShiftClick closure for both UI modification as well as the actualy
* SHIFT clicking logic
*/
var state = { previouslySelected: undefined, previouslyShiftSelected: undefined };



// "Your own click handler"
function onItemClick(elmTarget) {
 // Call the ShiftClick closure and let that handle the heavy lifting (passing in the callback as the last argument)
 ShiftClick.itemClick(elmTarget, state, '#my-list li', 'checked', handleItemClick);
 
 // INPUT YOUR CODE HERE
}

// Your own handleItemClick
function handleItemClick(elmTarget, selectedClass, itemChecked) {
 // Call the ShiftClick closure to do the UI updating
 ShiftClick.updateItemUI(elmTarget, selectedClass, itemChecked);
 
 // INPUT YOUR CODE HERE ... calling a backend service or logging ...
}



// JQuery extend to avoid html dom text to be selected
// Shamelessly copied from http://stackoverflow.com/questions/1319126/prevent-highlight-of-text
jQuery.fn.extend({ 
 disableSelection : function() { 
   this.each(function() { 
     this.onselectstart = function() { return false; }; 
     this.unselectable = "on"; 
     jQuery(this).css('-moz-user-select', 'none'); 
   }); 
 } 
});

$(document).ready(function(){
 // disable selection on #li text
 $('#my-list li').disableSelection();

 // Setup the "Your own click handler" for the selector
 $('#my-list li .checkbox').click( onItemClick );
});

and the ShiftClick closure/lib

/**
* Utility closure that implements range selection in a list of html elements
* SHIFT clicking
*/
(function (window, $, undefined) {
 var CHECKED = 'checked';
 var UNCHECKED = 'unchecked';
 
 /**
 * Implements the familiar SHIFT click functionality which can be found in most UI programs that allow
 * item selection. SHIFT clicking selects a range from the first item to the second item clicked
 */
 function itemClick(elmTarget, state, itemsSelector, selectedClass, handleItemClickCallback) {
  var startLoopIndex, endLoopIndex, previousSelectedIndex, previousShiftSelectedIndex, currentlySelectedIndex, items;

  if (elmTarget.shiftKey) {
   var selectedItems = $(itemsSelector + '.' + selectedClass);
   
   // The user is selecting the second item in the range
   if (selectedItems.length) {
    items = $(itemsSelector);
    previousSelectedIndex = items.index(state.previouslySelected);
    currentlySelectedIndex = items.index( $(elmTarget.target).closest('li'));

    // Clear previous range if any
    if (state.previouslyShiftSelected !== undefined) {
     previousShiftSelectedIndex = items.index(state.previouslyShiftSelected);
     startLoopIndex = Math.min(previousShiftSelectedIndex, currentlySelectedIndex);
     endLoopIndex = Math.max(previousShiftSelectedIndex, currentlySelectedIndex);

     for (var i = startLoopIndex; i <= endLoopIndex; i++) {
      handleItemClickCallback && handleItemClickCallback(items.eq(i), selectedClass, UNCHECKED);
     }
    }
    
    // Select current range
    startLoopIndex = Math.min(previousSelectedIndex, currentlySelectedIndex);
    endLoopIndex = Math.max(previousSelectedIndex, currentlySelectedIndex);

    for (var i = startLoopIndex; i <= endLoopIndex; i++) {
     handleItemClickCallback && handleItemClickCallback(items.eq(i), selectedClass, CHECKED);
    }
   }
   // The user have not normal clicked an item before and starts with SHIFT clicking
   else {
    handleItemClickCallback && handleItemClickCallback(elmTarget.target, selectedClass);
   }
   state.previouslyShiftSelected = $(elmTarget.target).closest('li');
  }
  
  // Normal clicking
  else {
   state.previouslySelected =  $(elmTarget.target).closest('li');

   // Reset previously SHIFT selected items
   state.previouslyShiftSelected = undefined;
   handleItemClickCallback && handleItemClickCallback(elmTarget.target, selectedClass);
  }
 }

 /**
 * Handles the actual UI modification to make the UI reflect the items selected
 * Handles one item at a time
 */
 function updateItemUI(elmTarget, selectedClass, itemChecked, selectCallback) {
  
  var elmParentLi = $(elmTarget).closest('li');
  if (itemChecked == CHECKED) {
   elmParentLi.addClass(selectedClass);
  }
  else if (itemChecked == UNCHECKED) {
   elmParentLi.removeClass(selectedClass);
  }
  else {
   elmParentLi.toggleClass(selectedClass);
  }

  var checked = elmParentLi.hasClass(selectedClass);
  selectCallback && selectCallback(elmParentLi.attr('data-id'), checked);
 }

 /**
 * Public methods
 */
 ShiftClick = {
  itemClick: itemClick,
  updateItemUI: updateItemUI
 };

})(window, jQuery);