Офис НП AMWAY в Ярославле
Офис Амвей в Ярославле
На карте Офис AMWAY в ЯрославлеПрием и выдача заказов, презентация продукции Амвей, мастер–классы, вопросы по бизнесу Amway:
Адрес: улица Валентины Терешковой, дом 1 (Вход со двора)
Телефон: +7 (920) 112-00-91
Email: matyxho@mail.ru
Сайт: https://www.amway.ru/user/lebedem
Визитка: http://yar.meweb.ru
Иерархия статей
Статьи » Программирование » Ajax кнопки Like Dislike для статей
Сниппет
Несложная реализация кнопок Нравится / Не нравится для статей на вашем проекте с использованием JQuery + Ajax + PHP + Cookie. Иногда весьма полезно знать отношение пользователей к вашим статьям, и эти кнопки немного помогут нам в этом.
Ajax кнопки Like Dislike для статей
Опубликовал  Pisatel Pisatel Добавлено  02-03-2015 11:51 02 Март 2015 11:51:03 22193  Прочтений 22193 Прочтений
 printer
Сегодня будем создавать ajax плюшку для наших статей в виде кнопок Like / Dislike (Нравится / Не нравится). Итак, начнем. По ходу кода буду давать небольшие комментарии. Для начала создаем таблицу в бд article_like, куда и будем заносить количество лайков / дислайков. Априори подразумевается, что у вас уже имеются статьи и у каждой из них есть свой уникальный id, который нам понадобится для идентификации (будет записываться в поле article_like_id. Структура создаваемой таблицы:

Код: SQL
    CREATE TABLE article_like (

like_id MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,

like_article_id MEDIUMINT(8) UNSIGNED NOT NULL,

like_like INT(10) UNSIGNED NOT NULL,

like_dislike INT(10) UNSIGNED NOT NULL,

PRIMARY KEY (like_id)

) ENGINE=MyISAM;




Таблица создана. Далее — разметка и сам вывод. Для иконок я буду использовать шрифт Font Awesome: он, конечно, великоват немного, но смотрится в итоге весьма кошерно. Для удобства подключения создадим небольшой файл (чтобы не прописывать лишний раз подключение к бд, плюс небольшая функция, взятая из cms PHP–Fusion для проверки числа), назовем его, например, config.php, и затем будем лишь вызывать на нужных страницах

Код: PHP
<?php

// создаем подключение к бд (данные вписываем свои)

$link = mysqli_connect("myhost", "myuser",

"mypass", "mydb") or die("Error ".mysqli_error($link));

// функция проверки числа

function isnum($value) {

if (!is_array($value)) {

return (preg_match("/^[0-9]+$/", $value));

} else {

return false;

}

}

?>




Теперь — подключение стиля и скриптов (размещаем на странице статьи)

Код: HTML5
<!-- подключаем файл стилей и файл js (последний можно подключить в подвал сайта

по умолчанию использую папку /inc/ для файлов, вы можете назвать ее как угодно -->

<head>

<link href='/like_dislike.css' rel='stylesheet' />

<script src='inc/jquery_1.11_min.js'></script>

<script src='inc/like_dislike.js'></script>

</head>




Теперь сам скрипт, который вставляем так же на страницу со статьей

Код: PHP
// подключаем наш config.php

require_once "config.php";

// подключение к бд и выборка

// выборку делаем по конкретной статье, за это отвечает параметр $_GET['article_id'], который берем из адреса страницы

// например, адрес у нас такой meweb.ru/articles.php?article_id=65

if (isset($_GET['article_id']) && isnum($_GET['article_id'])) {

$lresult = mysqli_query($link, "SELECT like_like, like_dislike FROM article_like WHERE like_article_id='".$_GET['article_id']."' LIMIT 1");

if (mysqli_num_rows($lresult)>0) {

// если получен корректный ответ- создаем массив и задаем значение переменных

$ldata = mysqli_fetch_assoc($lresult);

$like = $ldata['like_like'];

$unlike = $ldata['like_dislike'];

} else {

// иначе- записываем для данной статьи значения 0 и 0 для лайков и дислайков

mysqli_query($link, "INSERT INTO article_like (like_article_id, like_like, like_dislike) VALUES ('".$_GET['article_id']."', '0', '0')");

$like = "0";

$unlike = "0";

}

// теперь пошла сама разметка и вывод информации о количестве

$lres = "<div class='tbl tbl-border ldapo'>";

$lres .= "<div class='ldap'><i class='fa fa-line-chart'></i> Понравилась статья?</div>";

$lres .= "<div class='ld-stats-bar'></div>";

$lres .= "<span id='status'></span>";

$lres .= "<div class='ldapb'>";

$lres .= "<i class='fa fa-2x fa-thumbs-o-up'></i><input type='button' value='".$like."' class='button_like' id='linkeBtn' data-articleid='".$_GET['article_id']."' />";

$lres .= "<i class='fa fa-2x fa-thumbs-o-down'></i><input type='button' value='".$unlike."' class='button_unlike' id='unlinkeBtn' data-articleid='".$_GET['article_id']."' />";

$lres .= "</div></div>";

echo $lres;

// очищаем результат и закрываем подключение к бд

mysqli_free_result($lresult);

mysqli_close($link);

}




Теперь мы создадим файл like_dislike.js, которым будем перехватывать событие click по кнопке с идентификаторами linkeBtn и unlinkeBtn соответственно и отсылать/принимать данные на сервер/с севера посредством технологии Ajax. Как всегда, буду давать комментарии по ходу

Код: JQUERY
        $(function() {

// для начала убираем атрибуты disabled у наших кнопок input (если они существуют)

$('#linkeBtn').removeAttr('disabled');

$('#unlinkeBtn').removeAttr('disabled');

// создаем массив уведомлений для удобства

var Locale = {

alike: 'Статья понравилась!',

adislike: 'Статья не понравилась!',

atime: 'Вы уже оставили отзыв. Попробуйте позже.',

aerr: 'Произошла неизвестная ошибка.'

};

// берем значение val с кнопок

var l_val = parseInt($('#linkeBtn').val(), 10);

var d_val = parseInt($('#unlinkeBtn').val(), 10);

// задаем немного переменных для последующей работы с ними

var like = 'like';

var dislike = 'dislike';

var n_total = l_val + d_val;

var w_like;

var w_dislike;

var st;

var stn;

var div_n = '<div class=\'ld-bar-none\'></div>';

var div_l = '<div class=\'ld-bar-like\' style=\'width:100%;\'></div>';

var div_d = '<div class=\'ld-bar-dislike\' style=\'width:100%;\'></div>';

if (n_total == 0) {

// если сумма значений двух кнопок равна 0 (никто еще не голосовал)

// выводим соответствующий див

st = div_n;

} else if (d_val == 0 && l_val > 0) {

// иначе, если есть лайки, но нет дислайков

// красим див зеленым на 100%

st = div_l;

} else if (l_val == 0 && d_val > 0) {

// иначе, если есть дислайки, а лайков 0

// красим див полностью красным

st = div_d;

} else {

// иначе, если есть и лайки, и дислайки, производим их подсчет

// в процентном соотношении друг к другу

// и красим дивы зеленым/красным в процентном соотношении лайков/дислайков к 100%

w_like = Math.round(Math.abs(l_val * 100 / n_total));

w_dislike = 100 - w_like;

st = '<div class=\'ld-bar-like\' style=\'width:'+w_like+'%;\'></div><div class=\'ld-bar-dislike\' style=\'width:'+w_dislike+'%;\'></div>';

}

// выводим все, что сделали

$('.ld-stats-bar').append(st);



$('#linkeBtn').click(function(e) {

// если пользователю понравилась статья и он кликнул на кнопку

// перехватываем и обрабатываем событие

// взяли и запомнили id статьи

var article_id = $(this).data('articleid');

// добавим атрибут disabled для кнопки

// чтобы исключить повторное нажатие

$(this).attr('disabled', 'disabled');

// отсылаем ajax-запрос на сервер

$.ajax({

url:'/inc/like_dislike_ajax.php',

type:'POST', // метод выбираем post, так надежнее

data:({'article_id': article_id, 'like': like}), // передаем ид статьи и статус (лайк)

// функция обработки удачного ответа сервера

success: function(data) {

if (data==1) {

// если ответ равен 1

$('.ld-stats-bar').fadeOut('fast').empty(); // скрываем и очищаем див текущего статуса

l_val = l_val+1; // добавили единицу к val кнопки

n_total = n_total+1; // добавили 1 голос к общему количеству

if (l_val > 0 && d_val == 0) {

// если есть лайки, но нет дислайков, красим в зеленый

stn = div_l;

} else {

// иначе- вычисляем процентное соотношение

w_like = Math.round(Math.abs(l_val * 100 / n_total));

w_dislike = 100 - w_like;

stn = '<div class=\'ld-bar-like\' style=\'width:'+w_like+'%;\'></div><div class=\'ld-bar-dislike\' style=\'width:'+w_dislike+'%;\'></div>';

}

// выводим статус-сообщение об успешно добавленном голосе

$('#status').html('<i class=\'fa fa-check-square-o\'></i> '+Locale.alike).css({'color': '#006400'}).fadeIn('slow', function() {

setTimeout(function() { // статус-сообщение исчезнет через 5 секунд

$('#status').fadeOut('fast');

$('.ld-stats-bar').fadeIn('slow').append(stn).delay(300); // и появится обновленная полоса рейтинга с задержкой в 300 мс

}, 5000);

});

$('#linkeBtn').val(l_val).css({'color':'#222'}); // обновим value у кнопки, добавив 1 голос

} else {

// иначе, если ответ от сервера не равен 1

$('.ld-stats-bar').fadeOut('fast'); // убираем полосу рейтинга

// выводим статус-сообщение о том, что пользователь уже голосовал

$('#status').html('<i class=\'fa fa-lock\'></i> '+Locale.atime).css({'color': '#880000'}).fadeIn('slow', function() { // сообщение исчезнет через 4 секунды

setTimeout(function() {

$('#status').fadeOut('fast');

$('.ld-stats-bar').fadeIn('slow').delay(300); // возвращаем полосу рейтинга без обновления с задержкой в 300 мс

}, 4000);

});

}

},

// если во время запроса произошел какой-либо сбой, обрабатываем ошибку

error: function() {

$('.ld-stats-bar').fadeOut('fast'); // убираем полосу рейтинга

$('#status').html('<i class=\'fa fa-exclamation-triangle\'></i> '+Locale.aerr).css({'color': '#d00000'}).fadeIn('slow', function() {

setTimeout(function() {

$('#status').fadeOut('fast');

$('.ld-stats-bar').fadeIn('slow').delay(300);

}, 4000); // через 4 секунды убираем статус-сообщение и показываем шкалу рейтинга

});

$('#linkeBtn').removeAttr('disabled').delay(3000); // убираем атрибут disabled

}

});

});

// далее всё то же самое, но с кнопкой дислайк

$('#unlinkeBtn').click(function(e) {

$(this).attr('disabled', 'disabled');

var article_id = $(this).data('articleid');

$.ajax({

url:'/inc/like_dislike_ajax.php',

type:'POST',

data:({'article_id': article_id, 'dislike': dislike}),

success: function(data) {

if (data==1) {

$('.ld-stats-bar').fadeOut('fast').empty();

d_val = d_val+1;

n_total = n_total+1;

if (d_val > 0 && l_val == 0) {

stn = div_d;

} else {

w_dislike = Math.round(Math.abs(d_val * 100 / n_total));

w_like = 100 - w_dislike;

stn = '<div class=\'ld-bar-like\' style=\'width:'+w_like+'%;\'></div><div class=\'ld-bar-dislike\' style=\'width:'+w_dislike+'%;\'></div>';

}

$('#status').html('<i class=\'fa fa-check-square-o\'></i> '+Locale.adislike).css({'color': '#d00000'}).fadeIn('slow', function() {

setTimeout(function() {

$('#status').fadeOut('fast');

$('.ld-stats-bar').fadeIn('slow').append(stn).delay(300);

}, 5000);

});

$('#unlinkeBtn').val(d_val).css({'color':'#222'});

} else {

$('.ld-stats-bar').fadeOut('fast');

$('#status').html('<i class=\'fa fa-lock\'></i> '+Locale.atime).css({'color': '#880000'}).fadeIn('slow', function() {

setTimeout(function() {

$('#status').fadeOut('fast');

$('.ld-stats-bar').fadeIn('slow').delay(300);

}, 4000);

});

}

},

error: function() {

$('.ld-stats-bar').fadeOut('fast');

$('#status').html('<i class=\'fa fa-exclamation-triangle\'></i> '+Locale.aerr).css({'color': '#d00000'}).fadeIn('slow', function() {

setTimeout(function() {

$('#status').fadeOut('fast');

$('.ld-stats-bar').fadeIn('slow').delay(300);

}, 4000);

});

$('#unlinkeBtn').removeAttr('disabled').delay(3000);

}

});

});

});




Переходим к обработчику запроса. В папке inc создаем файл like_dislike_ajax.php с содержимым

Код: PHP
<?php

// подключаем config.php

require_once "../config.php";

// берем имя хоста для записи в cookie

$ldomain = htmlspecialchars($_SERVER['HTTP_HOST']);

// проверяем наличие post-запроса, и только после этого скрипт выполняется

if (isset($_POST['article_id']) && isnum($_POST['article_id']) && ((isset($_POST['like']) && $_POST['like'] == "like") || (isset($_POST['dislike']) && $_POST['dislike'] == "dislike"))) {

// проверяем, если cookie отсутствует- создаем

if (!isset($_COOKIE["counter_like_".$_POST['article_id']])) {

// записываем в куки время хранения- 1 сутки

setcookie("counter_like_".$_POST['article_id'], "liked", time()+3600*24, "/", $ldomain);

// если статья понравилась

if (isset($_POST['like']) && $_POST['like'] == "like") {

// прибавляем один лайк в бд

$update = "like_like=like_like+1";

} elseif (isset($_POST['dislike']) && $_POST['dislike'] == "dislike") {

// если не понравилась- прибавляем один дислайк

$update = "like_dislike=like_dislike+1";

}

// обновляем запись в базе

mysqli_query($link, "UPDATE article_like SET ".$update." WHERE like_article_id='".$_POST['article_id']."'");

$exit = 1;

// отдаем ответ скрипту like_dislike.js равный 1

echo json_encode($exit);

// закрываем соединение

mysqli_close($link);

} else {

// если файл cookie уже есть и сутки еще не прошли- отдаем ответ равный 2 (любой)

$exit = 2;

echo json_encode($exit);

exit;

}

// если в запросе нет post-данных или произошла ошибка

// при проверке ид статьи на целое число- убиваем выполнение скрипта

} else { die("Access Denied!"); }

?>




Ну и последний (но далеко не маловажный) штрих — это стиль. Ниже будет дизайн самих кнопок, полосы статуса и статус–сообщений. Однако, это не все. Чуть ниже расскажу, как и куда это чудо дизайнерской мысли добавить.

Код: CSS
.tbl-border {

border: 1px solid #ccc;

border-radius: 5px;

}

.tbl {

font-size: 11px;

padding: 4px;

}

.button_like, .button_unlike {

border: none;

height: 32px;

padding-left: 40px;

vertical-align: middle;

background-color: #f3f3f3;

background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f3f3f3), color-stop(50%, #ddd), color-stop(50%, #d2d2d2), color-stop(100%, #dfdfdf));

background-image: -webkit-linear-gradient(top, #f3f3f3 0%, #ddd 50%, #d2d2d2 50%, #dfdfdf 100%);

background-image: -moz-linear-gradient(top, #f3f3f3 0%, #ddd 50%, #d2d2d2 50%, #dfdfdf 100%);

background-image: -o-linear-gradient(top, #f3f3f3 0%, #ddd 50%, #d2d2d2 50%, #dfdfdf 100%);

background-image: linear-gradient(top, #f3f3f3 0%, #ddd 50%, #d2d2d2 50%, #dfdfdf 100%);

border-right: 1px solid #dfdfdf;

border-bottom: 1px solid #b4b4b4;

border-radius: 5px;

-webkit-box-shadow: inset 0 1px 0 0 #fff, 0 1px 0 0 #d5d5d5, 0 -1px 2px 1px #efefef;

box-shadow: inset 0 1px 0 0 #fff, 0 1px 0 0 #d5d5d5, 0 -1px 2px 1px #efefef;

font: bolder 16px/1 "helvetica neue", helvetica, arial, sans-serif;

margin: 0;

text-shadow: 0 1px 1px #fff;

}

.button_like {

color: hsl(120, 25%, 50%);

}

.button_unlike {

color: hsl(0, 100%, 42%);

}

.button_like:hover, .button_unlike:hover {

background-color: #e5e5e5;

background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #e5e5e5), color-stop(50%, #d1d1d1), color-stop(50%, #c4c4c4), color-stop(100%, #b8b8b8));

background-image: -webkit-linear-gradient(top, #e5e5e5 0%, #d1d1d1 50%, #c4c4c4 50%, #b8b8b8 100%);

background-image: -moz-linear-gradient(top, #e5e5e5 0%, #d1d1d1 50%, #c4c4c4 50%, #b8b8b8 100%);

background-image: -o-linear-gradient(top, #e5e5e5 0%, #d1d1d1 50%, #c4c4c4 50%, #b8b8b8 100%);

background-image: linear-gradient(top, #e5e5e5 0%, #d1d1d1 50%, #c4c4c4 50%, #b8b8b8 100%);

-webkit-box-shadow: inset 0 1px 0 0 #f2f2f2, 0 1px 0 0 #c9c9c9, 0 -1px 2px 1px #e3e3e3;

box-shadow: inset 0 1px 0 0 #f2f2f2, 0 1px 0 0 #c9c9c9, 0 -1px 2px 1px #e3e3e3;

cursor: pointer;

}

.button_like:active, .button_unlike:active {

-webkit-box-shadow: inset 0 0 30px 0 #999, 0 1px 0 0 #fff;

box-shadow: inset 0 0 30px 0 #999, 0 1px 0 0 #fff;

}

.ldapo {

position: relative;

height: 34px;

margin: 5px 0;

}

.ldap {

font-size: 16px;

font-weight: bolder;

position: absolute;

left: 7px;

top: 13px;

vertical-align: middle;

text-shadow: 0 1px 0 #fff;

}

.ldapb {

display: inline;

text-align: right;

position: absolute;

right: 7px;

top: 6px;

vertical-align: middle;

}

.ldapb i.fa-thumbs-o-up, .ldapb i.fa-thumbs-o-down {

position: relative;

left: 26px;

top: 6px;

}

.ldapb i.fa-thumbs-o-up {

color: #008000;

}

.ldapb i.fa-thumbs-o-down {

color: #d00000;

}

.ldapo span {

position: absolute;

right: 25%;

top: 13px;

font-size: 14px;

font-weight: bold;

text-align: right;

}

.ld-stats-bar {

position: absolute;

right: 25%;

top: 19px;

height: 5px;

width: 330px;

font-size: 0;

line-height: 0;

border: 1px solid #c5c5c5;

-webkit-box-shadow: 2px 2px 5px rgba(0, 0, 0, .25);

-moz-box-shadow: 2px 2px 5px rgba(0, 0, 0, .25);

-o-box-shadow: 2px 2px 5px rgba(0, 0, 0, 25);

box-shadow: 2px 2px 5px rgba(0, 0, 0, .25);

background-color: #fff;

}

.ld-bar-like, .ld-bar-dislike, .ld-bar-none {

margin: 0;

height: 5px;

font-size: 0;

line-height: 0;

border: 0;

padding: 0;

outline: none;

}

.ld-bar-like {

float: left;

background-color: #008000;

}

.ld-bar-dislike {

float: right;

background-color: #d00000;

}

.ld-bar-none {

width: 100%;

background: -webkit-repeating-linear-gradient(-45deg, #f9f9f9, #f9f9f9 10px, #ccc 10px, #ccc 20px);

background: -moz-repeating-linear-gradient(-45deg, #f9f9f9, #f9f9f9 10px, #ccc 10px, #ccc 20px);

background: -o-repeating-linear-gradient(-45deg, #f9f9f9, #f9f9f9 10px, #ccc 10px, #ccc 20px);

background: repeating-linear-gradient(-45deg, #f9f9f9, #f9f9f9 10px, #ccc 10px, #ccc 20px);

}




Ну а далее — немного гемороя. Попробую объяснить подробнее. Качаем шрифт Font Awesome (на момент выхода статьи текущая версия 4.3.0), распаковываем шрифты по пути /inc/fonts/, берем файл font-awesome.min.css и переименовываем его в like_dislike.css, кидаем в папку /inc/, предварительно чуть изменив: в самый конец файла добавить тот стиль, что дан выше, плюс поменять в начале файла пути до шрифтов, заменив ../fonts/ на fonts/.

Что ж, похоже, на этом все. Лицезреть пример вы можете сразу под статьей. Будут вопросы — спрашиваем в комментариях. Всем всех благ и удачи во всех начинаниях.
Понравилась статья?
Метки для данной статьи
Похожие статьи
Поделиться:   
Последние активные темы форума
  Темы Просмотров Ответов Последние сообщения
folder Вопрос по переделке bb-кода
PHP, MySQL
22346 5 Pisatel
26. мая 2017
folder Вопросы по Ajax форме обратной связи
CMS PHP Fusion
68673 48 Ditrin
19. февраля 2017
folder BBCode YouTube Video Colorbox mod
CMS PHP Fusion
15369 2 Pisatel
10. декабря 2016
folder Как лучше создать собственную страницу?
CMS PHP Fusion
17913 17 Pisatel
11. мая 2016
folder Небольшие вопросы по скриптам магазина и катало...
PHP, MySQL
145025 80 Pisatel
11. января 2016
folder BBCode Code mod
CMS PHP Fusion
14429 0 Pisatel
31. августа 2015
folder Ajax Like Dislike Article Panel
CMS PHP Fusion
22570 16 Pisatel
07. июля 2015
folder Хлебные крошки / BreadCrumbs SEO Panel
CMS PHP Fusion
26274 17 Pisatel
04. июля 2015
folder Abbr Description BBCode
CMS PHP Fusion
7670 0 Pisatel
15. июня 2015
folder Плагин Email рассылки Mail To All by Pisatel
CMS PHP Fusion
37037 32 Pisatel
26. апреля 2015
folder Подозрительный трафик и прочие страшилки
Всякая хрень
11807 2 Ditrin
23. апреля 2015
folder Мод Newsletter - рассылка писем пользователям с...
CMS PHP Fusion
31057 13 Pisatel
10. апреля 2015
folder Мод отправки писем PHPMailer для PHP-Fusion
CMS PHP Fusion
128565 113 Ditrin
06. апреля 2015
folder Появление неизвестного файла subscriptions.php
CMS PHP Fusion
8850 2 Pisatel
06. апреля 2015
folder Autoban on IP
CMS PHP Fusion
23205 13 Pisatel
03. апреля 2015