Pull to refresh

Пишем свой MooTools-плагин.

Reading time 7 min
Views 2.9K
Доброго времени суток.
Это мой первый серьезный пост на Хабре, так что критика приветствуется.
Сегодня я расскажу о написании плагина для JavaScript-библиотеки MooTools на примере модального всплывающего окна.

HTML, CSS.

Что же из себя будет представлять наше модальное окно? Схематично его можно представить следующим образом.

Schema

С точки зрения HTML, всплывающее окно — это обычный блочный элемент (например, div) и еще один блочный элемент для создания полупрозрачного оверлея. Функциональный HTML-код будет содержать всего две строки:
<div id="Overlay"></div>
<div idPopup»>Сообщение в окне.</div>

CSS-код будет выглядеть так:
body
{
   font-family: Arial, Tahoma, Sans-Serif;
   font-size: 1em;
}

#Popup
{
   visibility: hidden;
   position: absolute;
   left: 50%;
   top: 50%;
   background-color: #FFF;
   padding: 10px;
}

#Overlay
{
   visibility: hidden;
   position: absolute;
   left: 0;
   top: 0;
   width: 100%;
   background-color: #000;
}

С помощью visibility: hidden мы намеренно прячем всплывающее окно и оверлей, чтобы их не было видно сразу после загрузки страницы. Внимательный читатель мог заметить, что у оверлея в данный момент нулевая высота и всплывающее окно находится не в центре страницы (т.к. в центре страницы размещен левый верхний угол окна). Все это мы исправим в JavaScript.

JavaScript.

Теперь займемся JavaScript-кодом.
Пожалуй, полностью описывать синтаксис классов в MooTools я не буду, тут дается довольно полное описание. Давайте только взглянем на каркас класса, который возьмем для написания плагина, чтобы быстро разобраться, что тут к чему:
var MoodalBox = new Class({
   // Здесь мы указываем классы, из которых в наш класс будут скопированы свойства и методы.
   // В данном случае нам нужен метод setOptions() из класса Options.
   Implements: [Options],

   // Перечисляем возможные опции, передаваемые экземпляру класса и их значения по умолчанию.
   options: {
      optionName1: defaultValue1,
      optionName2: defaultValue2
   },

   // Это — конструктор нашего будущего класса.
   initialize: function(options)
   {
      // Выставляем значения опций, переданных в конструктор
      // (если туда ничего не передано, то берутся значения по умолчанию).
      this.setOptions(options);

      // Далее следует логика конструктора.
   }
});

Теперь усложним этот каркас тремя новыми методами: show (показать окно), hide (скрыть окно), setPosition (спозиционировать окно), также придумаем более осмысленные опции и добавим парочку аргументов в конструктор:
var MoodalBox = new Class({
   Implements: [Options],

   // Зададимся двумя опциями.
   options: {
      // Прозрачность оверлея после показа всплывающего окна.
      destinationOverlayOpacity: 0.7,
      
      // Возможность спрятать окно кликом по оверлею.
      allowManualClose: true
   },

   // В конструктор передаем два обязательных аргумента и необязательный аргумент с опциями.
   //  element — идентификатор элемента окна.
   //  overlay — идентификатор элемента оверлея.
   initialize: function(element, overlay, options)
   {
      this.setOptions(options);

      // Получаем элемент по его идентификатору.
      this.element = $(element);
      this.overlay = $(overlay);

      // Проверяем опцию возможности скрытия окна по клику.
      if (this.options.allowManualClose)
         // Цепляем на клик по оверлею метод скрытия.
         // Примечание: функция bind(param) возвращает метод this.hide, внутри которого переменная this
         // привязана к param. Если опустить вызов bind, тогда this внутри this.hide будет привязан к элементу,
         // событие в котором мы обрабатываем, т.е. к this.overlay.
         this.overlay.addEvent("click", this.hide.bind(this));

      // Получаем размеры окна для последующей его центровки.
      this.targetCoords = this.element.getCoordinates();

      // Эффекты для показывания/скрытия окна и оверлея.
      // Используется эффект, изменяющий заданное CSS-свойство во времени, в данном случае — это прозрачность.
      this.fx = {
         overlayAnimation: new Fx.Tween(this.overlay, { property: "opacity" }),
         elementAnimation: new Fx.Tween(this.element, { property: "opacity" })
      }
   },

   // Вызов этого метода покажет всплывающее окно.
   show: function()
   {
      // Выставляем элементы в нужные места.
      this.setPosition();
      
      // Запускаем анимацию показа (изменение прозрачности до видимых значений).
      this.fx.overlayAnimation.start(0, this.options.destinationOverlayOpacity);
      this.fx.elementAnimation.start(0, 1);
   },

   // Вызов этого метода скроет всплывающее окно.
   hide: function()
   {
      // Запускаем анимацию скрытия (изменение прозрачности до невидимых значений).
      this.fx.overlayAnimation.start(this.options.destinationOverlayOpacity, 0);
      this.fx.elementAnimation.start(1, 0);
   },

   // Здесь мы корректируем позицию всплывающего окна на странице и
   // размеры оверлея.
   setPosition: function()
   {
      this.element.setStyles({
         "marginLeft": -(this.targetCoords.width / 2),
         "marginTop": -(this.targetCoords.height / 2)
      });

      this.overlay.setStyles({
         "top": window.getScrollTop(),
         "height": window.getHeight()
      });
   }
});

Для использования класса необходимо создать его экземпляр и добавить на страницу кнопочку, нажатие на которую будет показывать окно. В результате HTML-код примет следующий вид:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   <title>Mootools plugin</title>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <link href="./Style.css" rel="Stylesheet" type="text/css" />
   <!-- Для работы нужно подключить библиотеку Mootools. -->
   <script src="../../MooToolsCore.js" type="text/javascript" language="javascript"></script>
   <!-- Тут подключаем наш плагин. -->
   <script src="./MoodalBox.js" type="text/javascript" language="javascript"></script>
   <script type="text/javascript" language="javascript">
   //<![CDATA[
      var popupFx = null;
      
      // Создадим экземпляр плагина после загрузки DOM-модели.
      // В конструктор передаем идентификаторы элементов окна и оверлея.
      window.addEvent("domready", function() { popupFx = new MoodalBox("Popup", "Overlay"); });
   //]]>
   </script>
</head>
<body>
   <input type="button" value="Show popup" onclick="popupFx.show();" />
   <div id="Overlay"></div>
   <div id="Popup">Сообщение в окне.</div>
</body>
</html>

Увидеть, как это работает можно здесь. А что же делать с опциями, которые можно изменять? Мы их просто передаем в конструктор в виде объекта. Например, так можно изменить прозрачность оверлея после показа окна:
popupFx = new MoodalBox("Popup", "Overlay", { destinationOverlayOpacity: 0.3 });

Более интересных результатов можно добиться с использованием класса Fx.Morph, который изменяет во времени одновременно несколько CSS-свойств. Результат с анимацией размеров можно посмотреть здесь. Если вам понравилась статья — буду писать еще.

P.S. Весь CSS-код можно было не выделять в отдельный файл, а инкапсулировать в JavaScript-классе, но тогда бы класс оброс лишними вызовами изменений CSS-свойств элемента и было бы сложнее уловить саму суть.

Кросс-пост из моего блога.

Резюмирую ссылки.

Простой пример.
Пример с анимацией размеров.

UPD. Зеркало (спасибо habracut):
Простой пример.
Пример с анимацией размеров.

UPD. Извините за хостинг, может кто посоветует что-нить хорошее и бесплатное… Вот здесь архив со всеми примерами.
Tags:
Hubs:
+48
Comments 61
Comments Comments 61

Articles