jQuery-скрипт для куков при использовании кэша MaxCache на WordPress
Этот пост адресован пользователям WordPress, у которых стоит кэширование с помощь MaxCache.
WordPress имеет в своем функционале две очень хорошие особенности, которые повышают юзабилити сайта для посетителей, оставляющих комментарии:
- Однажды оставив одобренный администратором сайта комментарий, посетитель избавляется от необходимости при каждом следующем комментарии вновь вводить свои данные, такие, как имя, e-mail, и адрес сайта.
- Если д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, так и не понял как подключить скрипт (весь блог прошерстил), если мне нужна только вторая его часть.
Просто добавляю код скрипта в какой-то JS-файл на сайте и подлючаю его?
очень нужно
Вторая часть без первой работать не будет, т.е. нужно использовать весь скрипт.
Да, если все условия, на которые я обратил внимание в статье, выполнены.
Мда, не знал, что jquery можно использовать и для таких вещей.
А можно ли узнать по-подробнее насчёт эффективности maxcache? Просто не нашёл на этом блоге. Может, плохо искал? :)
На странице скрипта вы найдете подробную информацию об этом. Я же лишь скажу, что разница с вариантом, когда этот скрипт не используется, огромна.
т.е. чтобы подключить ваш файл нужно:
в шаблоне с темой, в файле (header.php) прописать строчку
Затем сохранить Конечный код jQuery-скрипта с любым названием, с расширением js, т.е. допустим файл будет иметь название - comments.js
Загружаем его в любую директорию на сайт, и аналогично подключаем его в header.php
И все? Верно?
Пример кода вы неправильно вставили в комментарий, поэтому не знаю.
Да, действительно.
Т.е. в header.php достаточно прописать две строчки?
2
<script type="text/javascript" src="http://сайт/comment.js"></script>
Да, все верно.
Dimox,
хм.. в начале плагин Antispam Bee блокировал добавление комментариев. Отключила. Теперь добавление комментария проходит, но я не вижу ничего похоже на надпись:
“Спасибо, за Ваш комментарий! Он будет опубликован, как только его проверит администратор сайта.”
Более того, при работающем скрипте Максима, комментарий к посту не добавляется. Видимо беруться старые данные из кэша
Буду признательна, если подскажите, в чем может крыться проблема.
Я не знаю, в чем дело.
Спасибо. Мне первая часть скрипта помогла.
Не подскажете, вот этот код:
, что там Опера не так обрабатывает? Просто не припоминаю, чтоб у меня с ней проблемы были. Мне для общего развития. ;)
И еще вопрос. Хочу сделать так, чтоб в случае если в браузере куки от меня отсутствуют, в поля вводилась пару слов, типа “здесь имя”, а “здесь почта”. Я так понимаю - к строчке ниже надо прикрутить конструкцию else?
- что-то типа этого?
Я еще, почитаю, ваш блог. В любом случае, надо с jQuery потихоньку разбираться.
Может в литературу, на ваш взгляд хорошую, ткнете? О программировании понятие имею, c jQuery сегодня вот, столкнулся.
Мне сложно объяснить.
Да, правильно.
Скрипт помогает не только при использовании кеширующего скрипта Максима. Есть шаблоны, в которых и без него эта проблема существует. То, что комментарий ушел на модерацию видно, а вот данные свои приходится вводить в поля по новой каждый раз. Вчера выяснилось, что этим грешат шаблоны от yootheme.com. Лень было разбираться, впихнули этот скрипт, и все заработало как нужно. Так что спасибо за скрипт.