В своем прошлом топике, я описал базовые принципы работы с фреймворком backbone.js, теперь предлагаю перейти к практике и сделать что-нибудь полезное.
Предположим, что на нашем сайте часто используются разного вида попапы. Все они обладают схожими чертами, их можно открывать в большом количестве, перетаскивать, закрывать. Кроме того различаются активные и неактивные попапы, причем активный расположен поверх остальных и не затенен (хм… я бы сказал, что это уже больше напоминает window-manager).
Вобщем как-то так:
В соответствии с заветами ООП, попробуем разработать класс для попапа, от которого мы сможем наследоваться и создавать попапы на свой вкус с общим для всех поведением.
Скачиваем backbone.js, jquery, jquery ui, underscore.js и
Для начала создадим индексный файл с подключенными библиотеками, файлами нашего (еще не написанного) приложения и шаблонами.
<!doctype html><html><head> <title>Popup demo</title> <link rel="stylesheet" href="css/main.css" /> <!-- libs --> <script type="text/javascript" src="js/lib/jquery.js"></script> <script type="text/javascript" src="js/lib/jquery-ui.js"></script> <script type="text/javascript" src="js/lib/underscore.js"></script> <script type="text/javascript" src="js/lib/backbone.js"></script> <!-- app --> <script type="text/javascript" src="js/app/app.js"></script> <script type="text/javascript" src="js/app/views/PopupView.js"></script> <script type="text/javascript" src="js/app/views/ChildPopupView.js"></script> <!-- templates --> <script id="popup-template" type="text/template"> <div class="title"> <h1><%= title %></h1> </div> <div class="content"> <%= content %> </div> <div class="popup-close"> </div> </script> <script id="child-popup-template" type="text/template"> <div class="title"> <h1><%= title %></h1> <h3>i am a child</h3> </div> <div class="content"> <%= content %> </div> <div class="popup-close"> </div> </script> </head><body> <button id="popup-button">popup</button> <button id="child-popup-button">child popup</button></body></html>
В «body» у нас только 2 кнопки с помощью которых мы будем создавать попапы.
В этом файлике на клики по кнопкам навешивается код, создающий попапы, и добавляющий их в наш DOM.
function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } $(function () { $('#popup-button').click(function () { var popup = new PopupView(); $('body').append(popup.render().el); }); $('#child-popup-button').click(function () { var popup = new ChildPopupView(); $('body').append(popup.render().el); }); });
Так же я сюда запихнул функцию для получения случайного целого числа, она нам потом пригодится.
И теперь самое интересное!
var PopupView = Backbone.View.extend({ className: 'popup', events: { 'click .popup-close': 'close', 'mousedown': 'raise' }, initialize: function () { this.template = $('#popup-template').html(); this.width = '400px'; this.height = '350px'; this.top = getRandomInt(100, 400) + 'px'; this.left = getRandomInt(200, 500) + 'px'; this.context = { title: 'Default Title', content: 'Lorem ipsum dolor sit amet.' } $(this.el).css({ 'width': this.width, 'height': this.height, 'top': this.top, 'left': this.left, 'position': 'absolute' }); $(this.el).draggable(); }, /** * Рендерит попап и располагает его поверх остальных. */ render: function () { $(this.el).html(_.template(this.template, this.context)); // Делаем декущий попап активным $('.popup-active').removeClass('popup-active'); $(this.el).addClass('popup-active'); // Начальный z-index, минимальное значение которое может получить попап var max_z = 100; $('.popup').each(function () { var curr_z = parseInt($(this).css('z-index')); if (curr_z > max_z) { max_z = curr_z; } }); $(this.el).css({ 'z-index': max_z + 10 }); return this; }, /** * Поднимает попап наверх и делает его активным * по нажатию кнопки мыши. */ raise: function (e) { if (!$(this.el).hasClass('popup-active')) { var max_z = 0; $('.popup-active').removeClass('popup-active'); $('.popup').each(function () { var curr_z = parseInt($(this).css('z-index')); if (curr_z > max_z) { max_z = curr_z; } }); $(this.el).css({ 'z-index': max_z + 10 }); $(this.el).addClass('popup-active') } }, /** * Удаляет попап из DOM. */ close: function () { $(this.el).remove(); var max_z = 0; var top = null; // Выбираем самый верхний их оставшихся попапов $('.popup').each(function () { var curr_z = parseInt($(this).css('z-index')); if (curr_z > max_z) { max_z = curr_z; top = this; } }); // Делаем его активным if (top) { $(top).addClass('popup-active'); } } });
Здесь у нас описан попап, который станет родителем для всех остальных попапов, в нем реализован весь типичный функционал.
Теперь, для того чтобы создать новый попап, реализующий какое-то новое поведение, или использующий другой шаблон нам потребуется всего несколько строк кода.
var ChildPopupView = PopupView.extend({ initialize: function () { ChildPopupView.__super__.initialize.call(this); this.template = $('#child-popup-template').html(); this.context = { title: 'Child Title', content: 'Lorem ipsum dolor sit amet.' } } });
В этом потомке мы подключили другой шаблон и поменяли заголовок попапа. Вот так вот все просто!