29 октября 2011 г.

Облако тегов на ASP.Net MVC, с помощью JQuery

Сегодня будем делать такую полезную и нужную штуку, как облако тегов. Думаю, все понимают о чем речь, и для чего оно нужно, ведь на 99% сайтов красуются разнообразные "облачка".

Как всегда, вначале, я начал искать готовые JQuery-плагины, но поиски не удались, а поэтому будем делать все ручками. И работы там, кстати, не так уж и много.

Итак, займемся созданием простенького облака тегов по данным из базы, с использованием AJAX, JSON, и Javascript.
Разберем задачку более подробно.
После загрузки страницы должен происходить AJAX-запрос, который будет брать из базы необходимые для показа данные, и передавать их на страницу в JSON-формате. Полученные данные должны представляться пользователю в виде такого себе симпатичного облака тегов.

Сперва добавим все необходимое в представление:
   1:  <div id="tagsDiv">
   2:      <ul id="tagsList">
   3:      </ul>
   4:  </div>
   5:  <script src="/Scripts/myScript.js" type="text/javascript"></script>
   6:  <script src="/Scripts/jquery.json-2.2.min.js" type="text/javascript"></script>

myScript.js - скрипт, из которого будут происходить запросы.
jquery.json-2.2.min.js - скрипт для работы с JSON.
TagsList - наш декорированный список, который будет красиво оформлен с помощью следующих CSS-стилей:
   1:  #tagsDiv { width:350px; background-color:#5c87b2; text-align:center; padding:5px; 
overflow:auto; font-size:70%; font-family:arial; }
   2:  #tagsList { margin:0; padding:0; }
   3:  #tagsList li { list-style-type:none; float:left; margin:0 10px; height:35px; }
   4:  #tagsList li a { text-decoration:none; color:#ffffff; }
   5:  #tagsList li a:hover { text-decoration:underline;}

В качестве тегов будут выступать категории товаров из Northwind. Собственно, для отображения в облаке будет достаточно лишь названия категории, и ее ID, чтобы при выборе тега можно было дальше что-то делать с категорией, которую он представляет.

Понятно, что данные, возвращенные в JSON-формате нужно сериализировать. Для этого, и для простого представления тегов, мы создадим два класса, которые будут представлять собой модель, пришедшую в ответ на запрос:
   1:  [Serializable]
   2:  public class MCategoriesTags
   3:  {
   4:      public List<CategoryTag> CategoiesTags { get; set; }
   5:  }
   6:   
   7:  public class CategoryTag
   8:  {
   9:      public int catId { get; set; }
  10:      public string catName { get; set; }
  11:  }

Здесь, MCategoriesTags - класс, в объект которого будут сериализирован пришедший JSON-набор. Это просто набор простеньких объектов CategoryTag, с двумя свойствами. CategoryTag - представляет собой одну категорию.

Теперь перейдем к контроллеру. Здесь мы реализуем метод, который будет брать данные из базы данных, формировать набор для ответа, и возвращать это все дело скрипту:
   1:  public JsonResult Categories()
   2:  {
   3:      NorthwindDataContext dbContext = new NorthwindDataContext();
   4:   
   5:      var Categories = dbContext.Categories.OrderBy(c => Guid.NewGuid());
   6:   
   7:      var model = new MCategoriesTags { CategoiesTags = new List<CategoryTag>() };
   8:   
   9:      foreach (var category in Categories)
  10:      {
  11:          var Tag = new CategoryTag();
  12:          Tag.catId = category.CategoryID;
  13:          Tag.catName = category.CategoryName;
  14:                  
  15:          model.CategoiesTags.Add(Tag);
  16:      }
  17:   
  18:      return Json(model, JsonRequestBehavior.AllowGet);
  19:  }

Здесь все просто. Получаем из базы данных Northwind все категории, упорядоченные в случайном порядке. Проходим по всем категориям, и на основании каждой создаем новый объект тега, добавляя его в общий список модели.

Осталось лишь написать скрипт, который возьмет на себя всю работу на клиенте (файл myScript.js):
   1:  $(document).ready(function () {
   2:      GetCategories()
   3:  });
   4:   
   5:  function GetCategories() {
   6:      $.getJSON('/Home/Categories', null, function (data) {
   7:          $.each(data.CategoiesTags, function (index, tag) {
   8:              var li = $('<li>');
   9:              $("<a>").text(tag.catName).attr({ id: "c_" + tag.catId, href: "#",
onclick: "SelectTag('" + tag.catName + "'," + tag.catId + ");" }).appendTo(li);
  10:              var rnd = getRandomInt(10, 150);
  11:              li.children().css("fontSize", (rnd / 10 < 1) ? rnd / 10 + 1 + "em" :
(rnd / 10 > 2) ? "2em" : rnd / 10 + "em");
  12:              li.appendTo("#tagsList");
  13:          });
  14:      });
  15:  };
  16:   
  17:  function SelectTag(catName, catId) {
  18:      $('#tagsList a').css('text-decoration', 'none');
  19:      $('#tagsList #c_' + catId).css('text-decoration', 'underline');
  20:      alert('Your choise is: ' + catName + " with ID: " + catId);
  21:  };
  22:   
  23:  function getRandomInt(min, max) {
  24:      return Math.floor(Math.random() * (max - min + 1)) + min;
  25:  };

Получаем данные, и для каждого элемента из набора создаем новый пункт списка (<li>), который содержит в себе тег-ссылку, и добавляем его с помощью Jquery к списку tagsList.

Важный момент для облака тегов - сделать так, чтобы все теги не сливались в одно целое, и были легко различимы в общем списке. Чтобы проделать такое с нашим списком, мы будем задавать каждому следующему тегу разное значение font-size, с помощью случайно сгенерированного числа.

По нажатию на нужный тег, срабатывает функция SelectTag. В ней мы отмечаем выбранную ссылку нижнем подчеркиванием, и показываем в alert-е данные тега. В реальном случае нам нужно было бы показать товары выбранной категории.

Это все. Наше облако тегов готово.

Вот, что мы получаем при запуске проекта:

А после выбора понравившегося тега имеем:

Как по мне, так именно такой вариант "tags cloud" имеет место быть, ибо все эти вертящиеся сферы тегов уж слишком напрягают.

На этом все.
_____
Исходники