- PVSM.RU - https://www.pvsm.ru -

Система уведомлений о событиях на сайте (на примере аудиоплееера ВКонтакте)

Приветствую.

Думаю, многие, кто имеет аккаунт ВКонтакте и слушает там музыку, замечали, что если на одной вкладке включить трек, а затем уже на другой включить второй, первый трек уйдет в паузу. Примерно то же самое происходит с различными уведомлениями (новое сообщение, ответ на комментарий/запись и т.д.) — отображается оно только в активной вкладке. Кому интересно как это работет и каким образом сделать подобное у себя на сайте, милости просим за хабракат.

Теория

А реализуется всё это с помощью HTML5 Local Storage [1]. Возьмем тот же аудиопроигрыватель. При запуске трека в Local Storage сохраняется идентификатор окна и состояние проигрывателя (к примеру, 'play'). Если в другом окне (одного и того же домена, разумеется) запускается ещё один трек, все вкладки ставят свои проигрыватели на паузу. И так далее.

Практика

Хранить данные события будем в одном ключе, к примеру, 'notifier_event'. Писать туда будет строковое представление некоего объекта следующего вида:

var evt = {
	'notifier_id': 'aAr63gd2',
	'event': 'audiostate',
	'event_data': {'state': 'play'},
	'event_ts': Math.round(new Date().getTime() / 1000)
};

Поле notifier_id — это ID вкладки, из которой было послано событие; 'event' — название события, 'event_data' — соответственно данные события, 'event_ts' — Unix Timestamp. Время ивента нужно указывать чтобы событие смены значения ключа отрабатывалось всегда.

При получении события просто запускаем необходимый обработчик и выполняем все действия, которые относятся к полученному событию. Вот и всё :)

Листинги

Обработка события

/**
 * Binds storage key change event
 * @return void
 **/
Notifier.prototype.bindEvent = function()
{
	if (!this.isAvailable())
		return false;

	var t = this;

	$(window).bind('storage', function(e) {
		var evt = e.originalEvent;

		if (evt.key == t.m_localStorageKey) // Если измененный ключ - ключ хранения события, вызываем обработчика
			t.handleLsEvent(JSON.parse(evt.newValue));
	});
};

/**
 * Handles changes for certain localStorage event
 * @param Object evt
 **/
Notifier.prototype.handleLsEvent = function(evt)
{
	switch (evt.event)
	{
		case 'audiostate':
			this.handleAudioStateEvent(evt); // Обработчик нажатия кнопки play/pause проигрывателя
			break;
	}
};

/**
 * Handles audiostate event
 * @param Object evt
 * @return void
 **/
Notifier.prototype.handleAudioStateEvent = function(evt)
{
	if (evt.notifier_id != this.getNotifierId())
	{
		if (evt.event_data.state == 'play')
		{
			// Если какая-то вкладка начала проигрывание трека, ставим текущий проигрыватель на паузу
			player.pause();
		}
	}
};

Демо

Пример можно посмотреть здесь — трек 1 [2], трек 2 [3].

Исходники

Исходники можно скачать из репозитория GitHub [4].

Представленные в демо аудиозаписи распространяются под лицензией Attribution-ShareAlike License [5].

Автор: Shadez


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/uvedomleniya/16741

Ссылки в тексте:

[1] HTML5 Local Storage: http://www.w3schools.com/html/html5_webstorage.asp

[2] трек 1: http://gpdev.org/ls-notifier/?player=1

[3] трек 2: http://gpdev.org/ls-notifier/?player=2

[4] GitHub: https://github.com/Shadez/ls-notifier

[5] Attribution-ShareAlike License: http://creativecommons.org/licenses/by-sa/2.0/