Статья, в которой рассмотрим, как можно самостоятельно создать для сайта всплывающие сообщения (уведомления) подобно тому, как это выполняет jGrowl (плагин для jQuery).

Проект, рассматриваемый в рамках этой статьи, расположен на Github по адресу: https://github.com/itchief/how-to/tree/master/toast

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

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

Внешний вид всплывающих сообщений

В рамках этого проекта выполним создание 2 вариантов сообщений (с заголовком и без него).

Всплывающие сообщения (уведомления) для сайта (2 варианта)

По умолчанию сообщения будем выводить в правом верхнем углу страницы.

Описание использования созданной библиотеки для всплывающих сообщений

Библиотека для всплывающих сообщений состоит из 2 файлов ("toast.css" и "toast.js"). Преимуществом данной библиотеки является то, что она имеет очень маленький объем (менее 3Кбайт). В отличие от библиотеки jGrowl данный проект имеет реализацию всплывающих сообщений без использования библиотеки jQuery. Что является для некоторых проектов очень важным.

Подключение библиотеки для создания всплывающих сообщений к странице

Подключение библиотеки для создания уведомлений на страницу осуществляется посредством:

  • подключения CSS файла «toast.css» или «toast-with-header.css» к странице или включения содержимого одного из этих файлов в свой файл стилей;
  • добавления JavaScript файла «toast.js» или «toast-with-header.js» на страницу с помощью элемента script или включения содержимого одного из этих файлов в свой файл скриптов.
...
<link href="path/to/toast.css" rel="stylesheet">
...

<script src="path/to/toast.js"></script>

Создание всплывающих сообщений

Добавление на страницу всплывающих сообщений осуществляется посредством вызова статического метода add функции-конструктора Toast:

Синтаксис кода для всплывающих сообщений с заголовком:

/*
Параметры функции add:
header (строка) - название заголовка
body (строка) - текст сообщения
color (строка) - цвет в формате #rrggbb
autohide (булево) - скрывать ли автоматически всплывающее сообщение
delay (число) - количество миллисекунд, после которых сообщение будет автоматически скрыто
*/
Toast.add({
  header: 'Название заголовка',
  body: 'Текст сообщения',
  color: '#28a745',
  autohide: true,
  delay: 10000
});  

Для сообщений без заголовка:

/*
Параметры функции add:
text (строка) - текст сообщения
color (строка) - цвет в формате #rrggbb
autohide (булево) - скрывать ли автоматически всплывающее сообщение
delay (число) - количество миллисекунд, после которых сообщение будет автоматически скрыто
*/
Toast.add({
  text: 'Текст сообщения...',
  color: '#28a745',
  autohide: true,
  delay: 5000
});

Как разработать всплывающие сообщения для сайта

В этом проекте созданы различные варианты всплывающих сообщений. Подробно разберём только вариант, в котором они построены на "чистом" JavaScript и имеют внешний вид «без заголовка».

Создание всплывающих уведомлений начнём с разработки их HTML структуры:

<!-- HTML -->  
<div class="toast">
  Текст сообщения...
  <button class="toast__close" type="button">&times;</button>
</div>

Как видно, HTML синтаксис сообщений очень прост. Он состоит из элемента div с классом toast и button с toast-close.

Данные классы используются не только для оформления элементов, но и в коде JavaScript.

В CSS вышеприведённые классы применяются для привязки к HTML элементам следующих стилей:

/* CSS */ 
.toast {
  overflow: hidden;
  font-size: 0.875rem;
  background-color: rgba(255, 255, 255, 0.5);
  background-clip: padding-box;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 0.25rem;
  box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(10px);
  display: none;
  position: relative;
  padding: 0.75rem 2rem 0.75rem 0.75rem;
  overflow-wrap: break-word;
  word-break: break-word;
}

.toast__close {
  position: absolute;
  top: 0;
  right: 10px;
  padding: 0;
  background-color: transparent;
  border: 0;
  cursor: pointer;
  float: right;
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  color: #000;
  text-shadow: 0 1px 0 #fff;
  opacity: 0.6;
  appearance: button;
  margin: 0;
  font-family: inherit;
  border-radius: 0;
}

Добавлять сообщения (HTML код) на страницу будем динамически (с помощью JavaScript).

Класс "toast__close" в JavaScript будем использовать в роли селектора для получения кнопки "Закрыть". Для данной кнопки добавим обработку события "click". В обработчике этого события напишем действия, при выполнении которых будет осуществляться закрытие (скрытие) этого сообщения.

По умолчанию всплывающие сообщения после добавления их на страницу не отображаются ("display: none"). Отображение сообщения выполняется посредством добавления к нему класса "toast_show".

/* CSS */ 
.toast_show {
  display: block;
}  

Для скрытия отображаемого сообщения у него просто необходимо удалить класс "toast_show".

Задание цвета всплывающему сообщению будем осуществлять посредством "инлайнового" (с помощью атрибута "style") добавления к элементу с классом "toast" CSS-свойства background-color.

<!-- HTML -->
<div class="toast" style="background-color: rgba(255, 255, 255, 0.5);">
  Текст сообщения...
  <button class="toast__close" type="button">&times;</button>
</div>

Помещать создаваемые с помощью JavaScript всплывающие сообщения будем в контейнер (элемент) div с классом "toasts". Данный контейнер будем добавлять на страницу тоже с помощью JavaScript. Но осуществлять это будем только в том случае, если на странице его ещё нет.

HTML синтаксис контейнера:

<!-- HTML -->
<div class="toasts" style="position: fixed; top: 15px; right: 15px; width: 250px;"></div>    

Данный элемент по умолчанию настроен так, что он располагается в правом верхнем угла окна браузера и имеет ширину 250 пикселей. Если его нужно расположить в другом месте, то эти CSS свойства необходимо изменить в JavaScript.

Дополнительно в CSS добавим ещё следующий код. Он необходим для того чтобы задать отступ между сообщениями по вертикали.

.toast:not(:last-child) {
  margin-bottom: 0.75rem;
}

Код JavaScript состоит из функции-конструктора Toast, методов show и hide, и двух статических функций create и add.

// код JavaScript 
// функция-конструктор Toast (для создания объектов Toast)
var Toast = function (element, config) {
  // приватные переменные класса Toast
  var
    _this = this,
    _element = element,
    _config = {
      autohide: true,
      delay: 5000
    };
  // установление _config
  for (var prop in config) {
    _config[prop] = config[prop];
  }
  // get-свойство element
  Object.defineProperty(this, 'element', {
    get: function () {
      return _element;
    }
  });
  // get-свойство config
  Object.defineProperty(this, 'config', {
    get: function () {
      return _config;
    }
  });
  // обработки события click (скрытие сообщения при нажатии на кнопку "Закрыть")
  _element.addEventListener('click', function (e) {
    if (e.target.classList.contains('toast__close')) {
      _this.hide();
    }
  });
}
// методы show и hide, описанные в прототипе объекта Toast
Toast.prototype = {
  show: function () {
    var _this = this;
    this.element.classList.add('toast_show');
    if (this.config.autohide) {
      setTimeout(function () {
        _this.hide();
      }, this.config.delay)
    }
  },
  hide: function () {
    this.element.classList.remove('toast_show');
  }
};
// статическая функция для Toast (используется для создания сообщения)
Toast.create = function (text, color) {
  var
    fragment = document.createDocumentFragment(),
    toast = document.createElement('div'),
    toastClose = document.createElement('button');
  toast.classList.add('toast');
  toast.style.backgroundColor = 'rgba(' + parseInt(color.substr(1, 2), 16) + ',' + parseInt(color.substr(3, 2), 16) + ',' + parseInt(color.substr(5, 2), 16) + ',0.5)';
  toast.textContent = text;
  toastClose.classList.add('toast__close');
  toastClose.setAttribute('type', 'button');
  toastClose.textContent = '×';
  toast.appendChild(toastClose);
  fragment.appendChild(toast);
  return fragment;
};
// статическая функция для Toast (используется для добавления сообщения на страницу)
Toast.add = function (params) {
  var config = {
    header: 'Название заголовка',
    text: 'Текст сообщения...',
    color: '#ffffff',
    autohide: true,
    delay: 5000
  };
  if (params !== undefined) {
    for (var item in params) {
      config[item] = params[item];
    }
  }
  if (!document.querySelector('.toasts')) {
    var container = document.createElement('div');
    container.classList.add('toasts');
    container.style.cssText = 'position: fixed; top: 15px; right: 15px; width: 250px;';
    document.body.appendChild(container);
  }
  document.querySelector('.toasts').appendChild(Toast.create(config.text, config.color));
  var toasts = document.querySelectorAll('.toast');
  var toast = new Toast(toasts[toasts.length - 1], { autohide: config.autohide, delay: config.delay });
  toast.show();
  return toast;
}

Создание сообщений и их отображение пользователю выполняется с помощью вызова статической функции add:

// JavaScript
/*
  Параметры функции add:
  text (строка) - текст сообщения
  color (строка) - цвет в формате #rrggbb
  autohide (булево) - скрывать ли автоматически всплывающее сообщение
  delay (число) - количество миллисекунд, после которых сообщение будет автоматически скрыто
*/
Toast.add({
  text: 'Текст сообщения...',
  color: '#dc3545',
  autohide: false
});

Статическая функция add функции-конструктора Toast выполняет следующие действия:

  • создаёт контейнер для сообщений (элемент "div" с классом "toasts") и добавляет его перед закрывающим тегом "body";
  • добавляет в конец контейнера новое сообщение (toast) с помощью вызова статической функции Toast.create();
  • создает объект "Toast" посредством вызова функции-конструктора "Toast" (new Toast()) и сохраняет ссылку на данный объект в переменную toast;
  • вызывает метод "show" объекта toast (данный метод включает отображения уже созданного с помощью Toast.create() всплывающего сообщения);
  • возвращает в качестве результата выполнения ссылку на созданный объект (toast).