Офис НП 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 23374  Прочтений 23374 Прочтений
 printer
Сегодня будем создавать ajax плюшку для наших статей в виде кнопок Like / Dislike (Нравится / Не нравится). Итак, начнем. По ходу кода буду давать небольшие комментарии. Для начала создаем таблицу в бд article_like, куда и будем заносить количество лайков / дислайков. Априори подразумевается, что у вас уже имеются статьи и у каждой из них есть свой уникальный id, который нам понадобится для идентификации (будет записываться в поле article_like_id. Структура создаваемой таблицы:

Код: SQL
1
2
3
4
5
6
7
    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
1
2
3
4
5
6
7
8
9
10
11
12
13
<?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
1
2
3
4
5
6
7
<!-- подключаем файл стилей и файл 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
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
// подключаем наш 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
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
        $(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
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
<?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
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
.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/.

Что ж, похоже, на этом все. Лицезреть пример вы можете сразу под статьей. Будут вопросы — спрашиваем в комментариях. Всем всех благ и удачи во всех начинаниях.
Понравилась статья?
Метки для данной статьи
Похожие статьи
Поделиться:   
Последние активные темы форума
  Темы Просмотров Ответов Последние сообщения