Сейчас мы с вами будем разбираться с cookie (куки). Куки - это небольшой кусочек информации, который может храниться в браузере пользователя.

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

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

Кроме того, с куками можно работать не только из JavaScript, но и из PHP (там это нужно, например, для хранения авторизации пользователя), см. работа с куками на PHP при необходимости.

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

К сожалению, работа с куками в JavaScript реализована просто ужасно и без костылей тут не обойтись, а лучше просто использовать готовые библиотеки.

Итак, давайте приступим.

Основы работы с куками

К кукам, хранящимся в браузере, можно получить доступ с помощью document.cookie. С помощью этого свойства куки можно записывать и можно прочитывать.

В document.cookie куки хранятся просто в виде строки. Эта строка состоит из пар имя_куки=значение_куки , которые перечисляются через точку с запятой с пробелом '; '.

Пример: 'name=Вася; age=25'.

Чтобы записать в куки, нужно просто в document.cookie присвоить куку с ее именем:

document.cookie = 'name=Вася';

При записывании новой куки те куки, которые там уже были, не затрутся. Посмотрим на примере - будем постепенно записывать новые куки и сразу выводить текущее содержимое document.cookie:

document.cookie = 'name=Вася';
alert(document.cookie); //выведет 'name=Вася'

document.cookie = 'age=25';
alert(document.cookie); //выведет 'name=Вася; age=25'

Если устанавливать куку с тем же именем в разные значения - новое значение будет затирать предыдущее:

document.cookie = 'name=Вася';
alert(document.cookie); //выведет 'name=Вася'

document.cookie = 'name=Дима';
alert(document.cookie); //выведет 'name=Дима'

Когда вы будете экспериментировать с куками, имейте ввиду, что уже установленные куки никуда не деваются из document.cookie и мои примеры кода у вас могут работать не совсем так, как показано - вы будете видеть еще и ранее установленные куки.

Получение куки по ее имени

Итак, мы уже определи, что куки хранятся в виде простой строки, например, 'name=Вася; age=25; salary=1000'. Получается, чтобы найти, к примеру, значение куки с именем age, его нужно достать из это строки каким-нибудь способом: к примеру функциями работы со строками или регулярными выражениями.

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

Давайте попробуем написать регулярку, которая вытягивает значение куки с именем age:

document.cookie = 'age=25';
var age = document.cookie.match(/age=(.+?);/);
alert(age[1]); //выведет 25

Однако, эта регулярка не идеальна и при некоторых условиях может или не работать, или работать не правильно.

Во-первых, в нашей регулярке в конце стоит точка с запятой - разделитель разных кук в document.cookie. Но посмотрим внимательно на нашу строку с куками - 'name=Вася; age=25; salary=1000' - у последней куки нету точки с запятой в конце! И наша регулярка эту куку не возьмет.

Нужно ее модифицировать и сказать, что кука заканчивается или точкой с запятой, или концом строки. Модифицируем: /age=(.+?)(;|$)/.

Во-вторых, следует дописать часть регулярки перед именем куки - перед этим именем может быть пробел или начало строки, если кука первая. Допишем: /(^|\s)age=(.+?)(;|$)/.

Значение куки может быть пустым, к примеру, если мы в document.cookie записывали вот так: 'age='. Учтем это в нашей регулярке - заменим + на *. Заменим: /(^|\s)age=(.*?)(;|$)/.

Давайте теперь введем несохраняющие скобки, чтобы не плодить лишних карманов: /(?:^|\s)age=(.*?)(?:;|$)/.

А теперь давайте реализуем функцию getCookie(), которая параметром будет принимать имя произвольной куки и возвращать ее значение. Вот эта функция:

function getCookie(name) {
	var matches = document.cookie.match(new RegExp(
		'(?:^|\s)' + name + '=(.*?)(?:;|$)';
	));
	return matches[1];
}

Однако, у нас есть проблема: ведь в переменной name могут быть специальные символы (команды регулярных выражений), которые сломают нашу регулярку. Давайте заэкранируем все эти символы (заменим их на их же, но с экранирующем обратным слешем спереди):

name = name.replace(/([.$\/?*+\\{}|()\[\]^])/g, '\\$1') + '=(.*?);

С учетом этого исправления получим следующее:

function getCookie(name) {
	var matches = document.cookie.match(new RegExp(
		'(?:^|\s)' + name.replace(/([.$?*+\\\/{}|()\[\]^])/g, '\\$1') + '=(.*?)(?:;|$)';
	));
	return matches[1];
}

Теперь разберемся с matches[1]. Если кука существует - все хорошо, а вот если не существует - давайте вернем undefined:

if (matches) {return matches[1];} else {return undefined;}

Перепишем этот if в сокращенный вариант:

return matches ? matches[1] : undefined;

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

function getCookie(name) {
	var matches = document.cookie.match(new RegExp(
		'(?:^|\s)' + name.replace(/([.$?*+\\\/{}|()\[\]^])/g, '\\$1') + '=(.*?)(?:;|$)';
	));
	return matches ? matches[1] : undefined;
}

Теперь учтем, что некоторые браузеры выполняют url кодирование кук и раскодируем их обратно с помощью decodeURIComponent:

function getCookie(name) {
	var matches = document.cookie.match(new RegExp(
		'(?:^|\s)' + name.replace(/([.$?*+\\\/{}|()\[\]^])/g, '\\$1') + '=(.*?)(?:;|$)';
	));
	return matches ? decodeURIComponent(matches[1]) : undefined;
}

Это и есть готовая функция для получения нужной вам куки (взята отсюда learn.javascript.ru/cookie, я просто чуть подправил регулярку и объяснил как она работает).

Дополнительные настройки кук

Это еще не все: у кук есть дополнительные настройки, которые чаще всего желательно указать.

Эти настройки указываются после пары ключ=значение, каждое – после точки с запятой. Как-то так:

document.cookie = 'name=Вася; настройка1=значение1; настройка2=значение2';

Папка установки

Первая настройка, которую мы разберем - это папка сайта, для которой установлена кука. Это очень важная настройка, так как куки без нее работают совсем не так, как мы ожидаем - при установки куки мы думаем, что она будет доступна на всем сайте, а она будет доступна только в папке установки и ее подпапках.

Например: ваш сайт site.ru и вы, находясь на странице site.ru/folder/ установили куку. Так вот: эта кука будет доступна на странице site.ru/folder/, на странице site.ru/folder/subfolder/ и так далее, но не будет доступна, к примеру на странице site.ru/somefolder/.

Это очень неожиданное поведение. Чтобы исправить его существует настройка path. Обычно она используется так: path=/ - и кука устанавливается на всем сайте. Пример:

document.cookie = 'name=Вася; path=/';

Можно указать и конкретную папку, например path=/folder:

document.cookie = 'name=Вася; path=/folder';

Домен установки

Следующая настройка domain задает домен, для которого установлена кука. По умолчанию это текущий домен (но не его поддомены). Можно указать, что кука доступна именно на поддомене. К примеру, наш домен site.ru, а куку мы установим для forum.site.ru:

document.cookie = 'name=Вася; path=/; domain=forum.site.ru';

Если указать специальную маску .site.ru, то кука будет доступна на сайте и всех его поддоменах:

document.cookie = 'name=Вася; path=/; domain=.site.ru';

Время жизни

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

Для этого применяется настройка expires, в которую следует задавать момент времени, до которого живет кука. Этот момент устанавливается в формате GMT. Этот формат можно получить так: используем объект Date, устанавливаем в любое время, а потом вызываем метод toUTCString.

Давайте установим время жизни куки +1 день от текущего момента:

var date = new Date;
date.setDate(date.getDate() + 1);
date = date.toUTCString();
document.cookie = 'name=Вася; path=/; expires='+date;

Удаление кук

Куки удаляются интересным образом: нужно установить время их жизни в прошедшее время, ну или просто поставить его как -1. Давайте удалим нашу куку:

document.cookie = 'name=; path=/; expires=-1';

Библиотеки для работы с куками

Так как работа с куками в JavaScript реализована просто ужасно, существуют библиотеки, которые упрощают работу с ними. Изучите эти библиотеки самостоятельно: куки на чистом JavaScript и плагин jQuery.