jQuery-скрипт для куков при использовании кэша MaxCache на WordPress

7 декабря 2009 г.

Этот пост адресован пользователям WordPress, у которых стоит кэширование с помощь MaxCache.

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

  1. Однажды оставив одобренный администратором сайта комментарий, посетитель избавляется от необходимости при каждом следующем комментарии вновь вводить свои данные, такие, как имя, e-mail, и адрес сайта.
  2. Если дoбaвляeмый кoммeнтapий уходит на модерацию, то комментирующий все равно видит его на сайте, обычно с пометкой “коммент ожидает модерации”. Это дает посетителю понять, что комментарий успешно добавлен и не попал в спам-фильтр.

Проблема

Не так давно известный программист Максим создал очень полезный и нужный скрипт - кэш для WordPress (MaxCache), который существенно снижает нагрузку на сервер хостинга. Для моего тормознутого хостинга, на котором в данный момент мой блог dimox.name вынужден, так сказать, волочить свое существование, этот скрипт оказался спасением.

Но речь сейчас не о хостинге и не о скрипте MaxCache. Суть поста заключается в нижеследующем.

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

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

Я всегда стараюсь идти на встречу посетителям своих сайтов, поэтому я нашел выход из данной ситуации - написал на jQuery скрипт, который выполняет 2 утерянные после установки кэша функции.

Далее я подробненько опишу код скрипта. Если у вас нет желания все это читать, то можете сразу “перескочить” на конечный код скрипта.

Функция №1 - “вспоминаем” комментирующего

Чтобы избежать возможных конфликтов jQuery с другими фреймворками, создадим вот такую переменную, которую в дальнейшем и будем использовать:

1
var $j = jQuery.noConflict();

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

1
$j(function() { ... })

Для того, чтобы “вспомнить” нашего посетителя, который уже оставлял комментарий, мы создадим куки, в которых запишем его имя, e-mail и адрес сайта. Работать мы будешь, соответственно, с формой комментирования WordPress. Ее HTML-код выглядит примерно следующим образом (показываю только теги, необходимы нам):

1
2
3
4
5
6
<form action="/wp-comments-post.php" method="post" id="commentform">
  <input type="text" name="author" />
  <input type="text" name="email" />
  <input type="text" name="url" />
  ...
</form>

Чтобы скрипт, который мы получим в результате, у вас работал, убедитесь, что в вашем шаблоне WordPress у тега form используется точно такой же идентификатор (id=”commentform”).

У каждого input-тега в этой форме есть неизменный параметр name=”", за которые мы и будем цепляться при написании скрипта.

Куки мы будет создавать в тот момент, когда комментирующий нажимает кнопку “Дoбaвить кoммeнтapий”, для этого воспользуемся вот такой функцией:

1
$j('#commentform').submit(function() { ... });

В ней мы считаем значения полей input[name=”author”], input[name=”email”], input[name=”url”] и с помощью функции createCookie() (ее код я приведу в конце, дабы не раздувать размер статьи) поместим их в куки браузера:

1
2
3
4
5
6
7
$j('#commentform').submit(function() {

  createCookie('wp_commenter_author', $j('input[name="author"]').val(), 365);
  createCookie('wp_commenter_email', $j('input[name="email"]').val(), 365);
  createCookie('wp_commenter_url', $j('input[name="url"]').val(), 365);

});

В результате в браузере пользователя появляются куки со следующими названиями: wp_commenter_author, wp_commenter_email и wp_commenter_url. Цифра 365 указывает на количество дней хранения этих куков.

Можно было так и оставить вышеуказанный код создания куков, но в ходе тестирования обнаружился следующий момент. Как вы знаете, если вы залогинены на своем блоге, то при дoбaвлeнии кoммeнтapия поля имя/е-mail/сайт за ненадобностью не отображаются. Поэтому, поскольку этих полей нет, то в 3-х создаваемых куках записывается значение “undifined” (т.е. значение не определено). А, поскольку, далее мы будем эти куки считывать, то нам таких неопределенностей необходимо избежать. Поэтому мы делаем это следующим образом:

1
2
3
4
5
6
7
$j('#commentform').submit(function() {

  if ($j('input[name="author"]').length) createCookie('wp_commenter_author', $j('input[name="author"]').val(), 365);
  if ($j('input[name="email"]').length) createCookie('wp_commenter_email', $j('input[name="email"]').val(), 365);
  if ($j('input[name="url"]').length) createCookie('wp_commenter_url', $j('input[name="url"]').val(), 365);

});

Т.е. условием вида if ($j(’input[name=”author”]’).length) мы проверяем существования 3-х полей, и, если они есть на странице (т.е. это не залогиненный пользователь), то создаем куки со значениями данных полей.

Хорошо, куки создали. Теперь нужно их считать для последующий подстановки в эти поля. Создадим переменные, в которые сразу же заносим значения наших кук (код функции readCookie() будет приведен также в конце):

1
2
3
var author = readCookie('wp_commenter_author');
var email = readCookie('wp_commenter_email');
var url = readCookie('wp_commenter_url');

Куки прочитали, теперь нужно заполнить ими 3 наших поля (имя/е-mail/сайт):

1
2
3
if (author) $j('input[name="author"]').val(author);
if (email) $j('input[name="email"]').val(email);
if (url) $j('input[name="url"]').val(url);

Условие вида if (author) говорит нам, что, если кука существует в браузере пользователя, то мы вставляем ее значение в соответствующее поле. Эта проверка необходима, чтобы избежать ошибки, если кук нет.

В результате мы получаем вот такой конечный скрипт, который реализует 1-ю функцию - запоминает данные, введенные комментирующим, и в последствии автоматически подставляет их в поля.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var $j = jQuery.noConflict();

$j(function() {

  var author = readCookie('wp_commenter_author');
  var email = readCookie('wp_commenter_email');
  var url = readCookie('wp_commenter_url');

  if (author) $j('input[name="author"]').val(author);
  if (email) $j('input[name="email"]').val(email);
  if (url) $j('input[name="url"]').val(url);

  $j('#commentform').submit(function() {
    if ($j('input[name="author"]').length) createCookie('wp_commenter_author', $j('input[name="author"]').val(), 365);
    if ($j('input[name="email"]').length) createCookie('wp_commenter_email', $j('input[name="email"]').val(), 365);
    if ($j('input[name="url"]').length) createCookie('wp_commenter_url', $j('input[name="url"]').val(), 365);
  });

})

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

Чтобы подобного избежать, мы доработаем наш скрипт.

Функция №2 - даем знать, что комментарий добавлен

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

1
<a href="<?php echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ) ?>"><?php printf(__('%1$s at %2$s'), get_comment_date(),  get_comment_time()) ?></a>

А если смотреть исходный HTML-код страницы WordPress-сайта, то должен быть примерно такой код:

1
<a href="адрес_страницы/#comment-123" title="02 февраля, 2008 в 10:06 пп">текст ссылки</a>

Сначала мы добавим новую куку, которая будет создаваться также при нажатии на кнопку “Добавить комментарий” и создадим переменную, в которую ее будем считывать:

1
2
3
4
5
6
var submitCheck = readCookie('wp_submit_check');

$j('#commentform').submit(function() {
  ...
  createCookie('wp_submit_check', '1', 1);
});

Ее значение ставим равным “1″ и срок ее хранения - 1 день.

Все, что мы будем делать дальше, будет работать только при условии, что значение куки “wp_submit_check” равно “1″.

1
if (submitCheck == '1') { ... }

А кука эта когда у нас появляется? Правильно - при отправке формы. Т.е. все манипуляции с кукой wp_submit_check сделаны для того, чтобы выполнять нижеследующие действия только тогда, когда отправлен комментарий, и посетителю нужно об этом сообщить.

Если кратко на словах, то мы будем делать следующее - после добавления комментария посетитель перенаправляется на страницу с адресом вида http://site.ru/postname/#comment-123, где цифра - это идентификатор добавленного комментария. Далее проверяем, есть ли уже на странице ссылка с точно таким же якорем (#comment-123), если нет, то показываем посетителю сообщение о том, что его комментарий добавлен.

Дальнейшие комментарии напишу в самом скрипте:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
if (submitCheck == '1') {

  // считываем URL из адресной строки браузера и заносим в переменную
  var href = window.location.href;

  // проверяем, находимся ли мы на странице вида http://site.ru/postname/#comment-123
  // (страница с таким адресом открывается всегда при добавлении комментария в WordPress)
  if (/.+#comment-(\d+)/ig.test(href)) {

    // получаем цифру из URL в адресной строке,
    // которая стоит после "#comment-",
    // и помещаем ее в переменную
    var cid = href.replace(/.+#comment-(\d+)/ig, '$1');

    // создаем регулярное выражение, которое будем использовать дальше,
    // и заносим его в переменную reg
    var reg = new RegExp('#comment-' + cid,'ig');

    // переменная, значение которой будем менять,
    // если ссылка с якорем найдется
    var commentIdFind = 0;

    // пробегаемся по каждой ссылке в комментариях
    $j('#commentlist a').each(function() {

      // тестируем URL ссылки (атрибут href) с помощью
      // регулярного выражения reg (см. выше)
      if (reg.test($j(this).attr('href'))) {

        // если нашли такую ссылку с якорем из адресной строки
        // (а это значит, что коммент выведен на страницу и ничего
        // дополнительно показывать посетителю не нужно),
        // то переменной commentIdFind ставим значение = 1
        // и удаляем куку wp_submit_check
        commentIdFind = 1;
        eraseCookie('wp_submit_check');
      }

    })

    // если commentIdFind = 0, получается, что ссылка не была найдена,
    // значит комментарий не выведен на страницу, и нужно показать сообщение
    if (commentIdFind == 0) {

      // выводим сообщение путем добавления тега <li></li> в конец списка с комментариями
      // и назначаем ему идентификатор вида comment-123,
      // где вместо цифры подставляется ID добавленного комментария,
      // для того, чтобы проскроллить страницу к этому сообщению
      // HTML-код сообщения измените под себя
      $j('#commentlist').append('<li id="comment-' + cid + '"><em><strong>' + author + '</strong>, спасибо за Ваш комментарий! Он будет опубликован, как только его проверит администратор сайта.</em></li>');

      // считываем юзер-агента для определения браузера Opera,
      // чтобы применить к нему особые стили
      var userAgent = navigator.userAgent.toLowerCase();
      if (/opera/.test(userAgent)) { var top = 'html'; } else { var top = 'html, body'; }

      // определяем расстояние от верхнего края браузера
      // до элемента с нашим сообщением, заносим в переменную
      var offset = $j('#comment-' + cid).offset().top;

      // плавно прокручиваем окно браузера до сообщения,
      // которое показываем посетителю
      $j(top).animate({scrollTop: offset}, 500);
    }

  // если мы ушли со странице вида http://site.ru/postname/#comment-123,
  // то удаляем куку wp_submit_check
  } else {
    eraseCookie('wp_submit_check');
  }

}

В результате выполнения этой части кода комментатор увидит вот такое сообщение (естественно, если выполнены все вышеописанные условия):

%username%, спасибо за Ваш комментарий! Он будет опубликован, как только его проверит администратор сайта.

Конечный код jQuery-скрипта

В итоге у нас получился вот такой скрипт (для тех, кто не читал мои подробности по коду - обратите внимание на условия работы скрипта: условие раз, условие два):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
function createCookie(name,value,days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  }
  else var expires = "";
  document.cookie = name+"="+value+expires+"; path=/";
}
function readCookie(name) {
  var nameEQ = name + "=";
  var ca = document.cookie.split(';');
  for(var i=0;i < ca.length;i++) {
    var c = ca[i];
    while (c.charAt(0)==' ') c = c.substring(1,c.length);
    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
  }
  return null;
}
function eraseCookie(name) {
  createCookie(name,"",-1);
}

var $j = jQuery.noConflict();

$j(function() {

  var author = readCookie('wp_commenter_author');
  var email = readCookie('wp_commenter_email');
  var url = readCookie('wp_commenter_url');
  var submitCheck = readCookie('wp_submit_check');

  if (author) $j('input[name="author"]').val(author);
  if (email) $j('input[name="email"]').val(email);
  if (url) $j('input[name="url"]').val(url);

  $j('#commentform').submit(function() {
    if ($j('input[name="author"]').length) createCookie('wp_commenter_author', $j('input[name="author"]').val(), 365);
    if ($j('input[name="email"]').length) createCookie('wp_commenter_email', $j('input[name="email"]').val(), 365);
    if ($j('input[name="url"]').length) createCookie('wp_commenter_url', $j('input[name="url"]').val(), 365);
    createCookie('wp_submit_check', '1', 1);
  });

  if (submitCheck == '1') {

    var href = window.location.href;

    if (/.+#comment-(\d+)/ig.test(href)) {

      var cid = href.replace(/.+#comment-(\d+)/ig, '$1');
      var reg = new RegExp('#comment-' + cid,'ig');
      var commentIdFind = 0;

      $j('#commentlist a').each(function() {
        if (reg.test($j(this).attr('href'))) {
          commentIdFind = 1;
          eraseCookie('wp_submit_check');
        }
      })
      if (commentIdFind == 0) {
        $j('#commentlist').append('<li id="comment-' + cid + '"><em><strong>' + author + '</strong>, спасибо за Ваш комментарий! Он будет опубликован, как только его проверит администратор сайта.</em></li>');
        var userAgent = navigator.userAgent.toLowerCase();
        if (/opera/.test(userAgent)) { var top = 'html'; } else { var top = 'html, body'; }
        var offset = $j('#comment-' + cid).offset().top;
        $j(top).animate({scrollTop: offset}, 500);
      }
    } else {
      eraseCookie('wp_submit_check');
    }

  }

})

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

Теги: , , , автор: Dimox | рубрика jQuery

Комментарии (43): »

  1. Dimox, так и не понял как подключить скрипт (весь блог прошерстил), если мне нужна только вторая его часть.

    Просто добавляю код скрипта в какой-то JS-файл на сайте и подлючаю его?

    очень нужно

    @
  2. Вторая часть без первой работать не будет, т.е. нужно использовать весь скрипт.

    Просто добавляю код скрипта в какой-то JS-файл на сайте и подлючаю его?

    Да, если все условия, на которые я обратил внимание в статье, выполнены.

  3. Мда, не знал, что jquery можно использовать и для таких вещей.
    А можно ли узнать по-подробнее насчёт эффективности maxcache? Просто не нашёл на этом блоге. Может, плохо искал? :)

  4. А можно ли узнать по-подробнее насчёт эффективности maxcache?

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

  5. т.е. чтобы подключить ваш файл нужно:
    в шаблоне с темой, в файле (header.php) прописать строчку

    Затем сохранить Конечный код jQuery-скрипта с любым названием, с расширением js, т.е. допустим файл будет иметь название - comments.js
    Загружаем его в любую директорию на сайт, и аналогично подключаем его в header.php

    И все? Верно?

  6. Пример кода вы неправильно вставили в комментарий, поэтому не знаю.

  7. Да, действительно.
    Т.е. в header.php достаточно прописать две строчки?

    1
    2
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script type="text/javascript" src="http://сайт/comment.js"></script>
  8. Dimox,
    хм.. в начале плагин Antispam Bee блокировал добавление комментариев. Отключила. Теперь добавление комментария проходит, но я не вижу ничего похоже на надпись:
    “Спасибо, за Ваш комментарий! Он будет опубликован, как только его проверит администратор сайта.”
    Более того, при работающем скрипте Максима, комментарий к посту не добавляется. Видимо беруться старые данные из кэша
    Буду признательна, если подскажите, в чем может крыться проблема.

  9. Спасибо. Мне первая часть скрипта помогла.
    Не подскажете, вот этот код:

    1
    if (/opera/.test(userAgent)) { var top = 'html'; } else { var top = 'html, body'; }

    , что там Опера не так обрабатывает? Просто не припоминаю, чтоб у меня с ней проблемы были. Мне для общего развития. ;)

    И еще вопрос. Хочу сделать так, чтоб в случае если в браузере куки от меня отсутствуют, в поля вводилась пару слов, типа “здесь имя”, а “здесь почта”. Я так понимаю - к строчке ниже надо прикрутить конструкцию else?

    1
    if (author) $j('input[name="author"]').val(author);
    1
    if (author) $j('input[name="author"]').val(author) else $j('input[name="author"]').val('Ку-ку');

    - что-то типа этого?
    Я еще, почитаю, ваш блог. В любом случае, надо с jQuery потихоньку разбираться.
    Может в литературу, на ваш взгляд хорошую, ткнете? О программировании понятие имею, c jQuery сегодня вот, столкнулся.

    @
  10. что там Опера не так обрабатывает?

    Мне сложно объяснить.

    Я так понимаю - к строчке ниже надо прикрутить конструкцию else?

    Да, правильно.

  11. Скрипт помогает не только при использовании кеширующего скрипта Максима. Есть шаблоны, в которых и без него эта проблема существует. То, что комментарий ушел на модерацию видно, а вот данные свои приходится вводить в поля по новой каждый раз. Вчера выяснилось, что этим грешат шаблоны от yootheme.com. Лень было разбираться, впихнули этот скрипт, и все заработало как нужно. Так что спасибо за скрипт.

    @

Присоединяйтесь к обсуждению!

Отправляя кoммeнтapий, вы автоматически принимаете правила кoммeнтиpoвaния на этом блоге.

Правила кoммeнтиpoвaния на блоге dimox.name:

  1. Первый кoммeнтapий всегда проходит премодерацию.
  2. В поле "URL блога" можно указывать только ссылку на главную страницу вашего блога. Ссылки на прочие веб-ресурсы (в том числе блоги/сплоги, созданные не для людей) будут удалены.
  3. Запрещается использовать в качестве имени комментатора слоганы/названия сайтов, рекламные фразы, ключевые и т.п. слова. В случае несоблюдения этого условия имя изменяется по усмотрению владельца блога. Просьба указывать нормальное имя или ник.
  4. Весьма вероятно, что короткий и неинформативный кoммeнтapий вида "Спасибо!", "Интересная статья", будет удален. Исключение составляют знакомые автору блога комментаторы.
  5. Комментарии не по теме удаляются.

Подписаться, не комментируя
  • Похожие статьи
  • Предыдущие из рубрики