Click here to Skip to main content
15,886,362 members
Articles / Web Development / HTML5
Tip/Trick

Interactive Menu

Rate me:
Please Sign up or sign in to vote.
4.95/5 (6 votes)
5 Jan 2014CPOL2 min read 15.3K   248   13   1
Concept of interactive menu based on user activity.

Introduction

In this post, I want to present one way of creating interactive menu based on specific user activity. The main idea is to show suitable menu for each user based on his previous actions. For this, I created a test ASP.NET MVC 3 application. It emulates the "Football News" web site where user can select a country to see its championship news. See the main menu below:

Image 1

Presentation

As I said, each user would have appropriate menu based on his actions. Let's look at them.

The first one is Pedro Duarte. He is from Spain and usually he clicks on "Spain" menu item, but also he is interested in what happens in England Championship. Sometimes, if the Spain and England news has been read, he visit German, Italy, and France Championships. Thus, if Pedro Duarte goes to the website, he see the next menu:

Image 2

Next user is Cole Jones. He is from England, therefore the most visited menu item is England Championship. Also, he usually visits Spain and Germany and sometimes Italy and France.

Image 3

Daniel Weber is from Germany:

Image 4

Antonio Rossi is from Italy:

Image 5

Lucas Martin is from France:

Image 6

So, the above pictures demonstrate the interactive menus that are presented in suitable view for each user. The user doesn't have to find this favorite Championship reading each menu item. He intuitively would know that his favorite items are emphasized and are on the top(left) of the list.

Using the Code

The data is stored in SDF database. For data manipulation, I use Entity Framework. The database structure is described below.

User table:

C#
[Table("Users")]
public class User
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [MaxLength(50)]
    public string Name { get; set; }
} 

Visit table:

C#
[Table("Visits")]
public class Visit
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [MaxLength(50)]
    public string ContentId { get; set; }
        
    public int UserId { get; set; }
} 

Database context:

C#
public class FanatContext : DbContext
{
    public FanatContext()
        : base("FanatConnection")
    {}

    public DbSet<User> Users { get; set; }

    public DbSet<Visit> Visits { get; set; }
} 

Connection string in web.config:

XML
<add name="FanatConnection" 
  connectionString="Data Source=|DataDirectory|Fanat.sdf" 
  providerName="System.Data.SqlServerCe.4.0"/> 

Next class initializes the SDF database:

C#
 public class FanatContextInitializer : CreateDatabaseIfNotExists<FanatContext>
{
    protected override void Seed(FanatContext context)
    {
        // USERS
        var userSpain = new User() { Name = "Pedro Duarte" };
        var userEngland = new User() { Name = "Cole Jones" };
        var userGerman = new User() { Name = "Daniel Weber" };
        var userItaly = new User() { Name = "Antonio Rossi" };
        var userFrance = new User() { Name = "Lucas Martin" };
        context.Users.Add(userSpain);
        context.Users.Add(userEngland);
        context.Users.Add(userGerman);
        context.Users.Add(userItaly);
        context.Users.Add(userFrance);
        context.SaveChanges();
        // FANS VISIT
        InitVisits(context, userSpain.Id, 100, 50, 20, 10, 5);
        InitVisits(context, userEngland.Id, 70, 150, 55, 30, 18);
        InitVisits(context, userGerman.Id, 42, 22, 110, 45, 10);
        InitVisits(context, userItaly.Id, 132, 29, 15, 200, 20);
        InitVisits(context, userFrance.Id, 69, 65, 50, 15, 70);

        base.Seed(context);
    }

    private static void InitVisits(FanatContext context, int userId,
        int spainVisits, int englandVisits, int germanVisits, int italyVisits, int franceVisits)
    {
        InitVisits(context, userId, ContenIds.Spain, spainVisits);
        InitVisits(context, userId, ContenIds.England, englandVisits);
        InitVisits(context, userId, ContenIds.Germany, germanVisits);
        InitVisits(context, userId, ContenIds.Italy, italyVisits);
        InitVisits(context, userId, ContenIds.France, franceVisits);
    }

    private static void InitVisits(FanatContext context, int userId, string contentId, int count)
    {
        if (count > 0)
        {
            for (int i = 0; i < count; i++)
            {
                var visit = new Visit()
                {
                    UserId = userId,
                    ContentId = contentId
                };
                context.Visits.Add(visit);
            }
            context.SaveChanges();
        }
    }
} 

Controller has one view action - Index. It returns menu model based on user information. Menu items are ordered by rate value. This value is equal to visits by user.

C#
public ActionResult Index()
{
    var menuMolel = new MenuModel();
    var userId = 0;

    int.TryParse(Request.Params["u"], out userId);
    menuMolel.SelectedId = userId;

    var items = new List<MenuItem>();
    items.Add(new MenuItem("Spain", ContenIds.Spain, GetVisits(userId, ContenIds.Spain)));
    items.Add(new MenuItem("England", ContenIds.England, GetVisits(userId, ContenIds.England)));
    items.Add(new MenuItem("Germany", ContenIds.Germany, GetVisits(userId, ContenIds.Germany)));
    items.Add(new MenuItem("Italy", ContenIds.Italy, GetVisits(userId, ContenIds.Italy)));
    items.Add(new MenuItem("France", ContenIds.France, GetVisits(userId, ContenIds.France)));

    menuMolel.Items.AddRange(items.OrderByDescending(x => x.Rate));
    menuMolel.Users.AddRange(GetUsers());

    return View(menuMolel);
} 
C#
private int GetVisits(int userId, string contentId)
{
    using (var context = new FanatContext())
    {
        return context.Visits.Where(x => x.UserId == userId && x.ContentId == contentId).Count();
    }
}

private IEnumerable<User> GetUsers()
{
    using (var context = new FanatContext())
    {
        return context.Users.ToList();
    }
} 

MenuItem and MenuMode classes:

C#
public class MenuItem
{
    public MenuItem()
    {}

    public MenuItem(string name, string contentId, double rate = 0)
    {
        this.Name = name;
        this.ContentId = contentId;
        this.Rate = rate;
    }

    public string Name { get; set; }

    public string ContentId { get; set; }

    public double Rate { get; set; }
} 
C#
public class MenuModel
{
    public MenuModel()
    {
        Items = new List<MenuItem>();
        Users = new List<User>();
    }

    public List<MenuItem> Items { get; set; }

    public List<User> Users { get; set; }

    public int SelectedId { get; set; }
} 

The menu items are ordered on the server but what about CSS emphasizing? Here, I'm using I2UI JavaScript library:

HTML
<script src="http://i2ui.com/Scripts/Downloads/i2ui-1.0.0.js" type="text/javascript"></script> 

To emphasize HTML tags, you need to add additional attribute "data-i2":

HTML
<div class="menu clear-fix" data-i2="css:['.from-item','.to-item']">
    @foreach (var item in Model.Items)
    {
        <div class="item" data-i2="rate:@item.Rate">@item.Name</div>
    }
</div> 

Here, the div with "menu" class takes "data-i2" attribute with the CSS selectors range: 'from-item' and 'to-item'. The inner div with "item" class takes the "data-i2" attribute with the rate value.

CSS range:

CSS
.from-item
{
    font-size: 12px;
    padding: 3px;
    margin: 3px;
    opacity: 0.5;
    border-radius: 3px;
    background-color: #649151;
    color: #fff;
}
.to-item
{
    font-size: 30px;
    padding: 10px;
    margin: 10px;
    opacity: 1;
    border-radius: 10px;
    background-color: #164C00;
    color: #fff;
} 

Also, you need to call emphasize function in JavaScript:

JavaScript
$(document).ready(function () {
    i2.emph();
}); 

Requirements

Visual Studio 2010

Need to have installed:

  • ASP.NET MVC 3
  • Microsoft SQL Server Compact 4.0
  • Entity Framework 4

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionMy vote of 5 Pin
Volynsky Alex9-Jan-15 9:27
professionalVolynsky Alex9-Jan-15 9:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.