diff --git a/app/Controllers/Api/Images/Comment.php b/app/Controllers/Api/Images/Comments/Create.php
similarity index 96%
rename from app/Controllers/Api/Images/Comment.php
rename to app/Controllers/Api/Images/Comments/Create.php
index 7331169..fd46abc 100644
--- a/app/Controllers/Api/Images/Comment.php
+++ b/app/Controllers/Api/Images/Comments/Create.php
@@ -1,11 +1,11 @@
Auth::userid(), ':wid' => $_GET['wid'], ':type'=>$_GET['vote']));
+ if (Vote::comment(Auth::userid(), $_GET['wid']) != $_GET['vote']) {
+ DB::query('DELETE FROM photos_comments_rates WHERE user_id=:id AND comment_id=:wid AND type=:type', array(':id'=>Auth::userid(), ':wid' => $_GET['wid'], ':type'=>Vote::comment(Auth::userid(), $_GET['wid'])));
+ }
+ } else if (Vote::comment(Auth::userid(), $_GET['wid']) === (int)$_GET['vote']) {
+ DB::query('DELETE FROM photos_comments_rates WHERE user_id=:id AND comment_id=:wid', array(':id'=>Auth::userid(), ':wid' => $_GET['wid']));
+ } else {
+ DB::query('UPDATE photos_comments_rates SET type=:type WHERE user_id=:id AND comment_id=:wid', array(':id'=>Auth::userid(), ':wid' => $_GET['wid'], ':type'=>$_GET['vote']));
+
+ }
+ if (Vote::comment(Auth::userid(), $_GET['wid']) === 1) {
+ $pos = true;
+ $neg = true;
+ } else if (Vote::comment(Auth::userid(), $_GET['wid']) === 0) {
+ $pos = false;
+ $neg = true;
+ } else {
+ $pos = false;
+ $neg = false;
+ }
+ $array = [
+ [1 => $pos, 0 => $neg],
+ [1 => Vote::countcommrates($_GET['wid'], 1), 0 => Vote::countcommrates($_GET['wid'], 0)],
+ Vote::countcommrates($_GET['wid'], -1)
+ ];
+
+
+ $json = json_encode($array);
+
+
+ header('Content-Type: application/json');
+ echo $json;
+ }
+ }
+}
diff --git a/app/Controllers/ApiController.php b/app/Controllers/ApiController.php
index 921150a..6c30e05 100644
--- a/app/Controllers/ApiController.php
+++ b/app/Controllers/ApiController.php
@@ -7,8 +7,9 @@ use \App\Core\Page;
use \App\Controllers\Api\{Login, Register};
use \App\Controllers\Api\Images\{Upload};
use \App\Controllers\Api\Images\Rate as PhotoVote;
-use \App\Controllers\Api\Images\Comment as PhotoComment;
-use \App\Controllers\Api\Images\CommentsLoad as PhotoCommentLoad;
+use \App\Controllers\Api\Images\Comments\Create as PhotoComment;
+use \App\Controllers\Api\Images\Comments\Load as PhotoCommentLoad;
+use \App\Controllers\Api\Images\Comments\Rate as PhotoCommentVote;
use \App\Controllers\Api\Profile\Update as ProfileUpdate;
class ApiController
{
@@ -29,6 +30,9 @@ class ApiController
public static function photocomment() {
return new PhotoComment();
}
+ public static function photocommentvote() {
+ return new PhotoCommentVote();
+ }
public static function photocommentload() {
return new PhotoCommentLoad();
}
diff --git a/app/Core/Routes.php b/app/Core/Routes.php
index fa9556b..056120d 100644
--- a/app/Core/Routes.php
+++ b/app/Core/Routes.php
@@ -17,9 +17,7 @@ class Routes
Router::get('/register', 'RegisterController@i');
Router::get('/photo/$id', 'PhotoController@i');
Router::get('/author/$id', 'ProfileController@i');
-
Router::post('/api/login', 'ApiController@login');
- Router::get('/api/photo/vote', 'ApiController@photovote');
Router::post('/api/register', 'ApiController@register');
@@ -34,6 +32,9 @@ class Routes
Router::post('/api/profile/update', 'ApiController@updateprofile');
Router::post('/api/photo/comment', 'ApiController@photocomment');
Router::post('/api/photo/getcomments/$id', 'ApiController@photocommentload');
+ Router::get('/api/photo/vote', 'ApiController@photovote');
+ Router::get('/api/photo/comment/rate', 'ApiController@photocommentvote');
+
} else {
Router::redirect('/login?return='.$_SERVER['HTTP_REFERER']);
}
diff --git a/app/Models/Comment.php b/app/Models/Comment.php
index 26d6427..827ae9e 100644
--- a/app/Models/Comment.php
+++ b/app/Models/Comment.php
@@ -1,7 +1,7 @@
i('content'), true)['aboutlive']['value'] != null) {
echo ' '.json_decode($user->i('content'), true)['aboutlive']['value'];
}
+ if ((int)Vote::countcommrates($this->c['id'], -1) >= 1) {
+ $commclass = 'pro';
+ $symb = '+';
+ } else if ((int)Vote::countcommrates($this->c['id'], -1) < 0) {
+ $commclass = 'con';
+ $symb = '-';
+ } else if ((int)Vote::countcommrates($this->c['id'], -1) === 0) {
+ $commclass = '';
+ }
echo '
Фото: '.Photo::fetchAll($this->c['user_id']).'
'.$this->c['body'].'
';
diff --git a/app/Models/Vote.php b/app/Models/Vote.php
index f132a7a..71152f5 100644
--- a/app/Models/Vote.php
+++ b/app/Models/Vote.php
@@ -20,6 +20,23 @@ class Vote
}
+ }
+
+ public static function comment($user_id, $pid)
+ {
+ $result = DB::query('SELECT * FROM photos_comments_rates WHERE user_id=:uid AND comment_id=:pid', array(':uid' => $user_id, ':pid' => $pid));
+ if (!empty($result)) {
+ $type = $result[0]['type'];
+ if ($type < 0) {
+ $type = -1;
+ }
+
+ return $type;
+ } else {
+ return -1;
+ }
+
+
}
public static function count( $pid) {
@@ -34,6 +51,22 @@ class Vote
}
return $votes;
}
+ public static function countcommrates($pid, $type) {
+ if ($type === -1) {
+ $result = DB::query('SELECT * FROM photos_comments_rates WHERE comment_id=:pid', array(':pid' => $pid));
+ } else {
+ $result = DB::query('SELECT * FROM photos_comments_rates WHERE comment_id=:pid AND type=:type', array(':pid' => $pid, ':type'=>$type));
+ }
+ $votes = 0;
+ foreach ($result as $r) {
+ if ($r['type'] === 1) {
+ $votes++;
+ } else {
+ $votes--;
+ }
+ }
+ return $votes;
+ }
public static function token()
{
diff --git a/static/js/comments.js b/static/js/comments.js
new file mode 100644
index 0000000..bb7eaf8
--- /dev/null
+++ b/static/js/comments.js
@@ -0,0 +1,187 @@
+var navLock = false;
+var lastQuoteLinkBlock = true;
+
+$(document).ready(function()
+{
+ // Изменение рейтинга комментария (с учётом форматирования)
+ function setComVote(cell, rating)
+ {
+ if (rating > 0) cell.removeClass('con').addClass('pro').html('+' + rating); else
+ if (rating < 0) cell.removeClass('pro').addClass('con').html('–' + parseInt(-rating));
+ else cell.removeClass('pro con').html(0);
+ }
+
+
+ // Голосование за комментарии
+ $(document).on('click', '.w-btn', function()
+ {
+ var vote = $(this).attr('vote');
+ if (vote != 0 && vote != 1) return false;
+
+ var voted = $(this).is('.voted');
+ $(this).toggleClass('voted');
+
+ var diff = (vote == 1 && !voted || vote == 0 && voted) ? 1 : -1;
+
+ var otherButton = $(this).siblings('.w-btn');
+ var votedOther = otherButton.is('.voted');
+
+ if (votedOther)
+ {
+ otherButton.removeClass('voted');
+ diff *= 2;
+ }
+
+ var cell = $(this).siblings('.w-rating');
+ var rating = parseInt(cell.is('.con') ? -cell.html().substring(1) : cell.html());
+
+ setComVote(cell, rating + diff);
+
+
+ var cell_ext = $(this).siblings('.w-rating-ext');
+ cell_ext.addClass('active-locked');
+
+ var pro = $('.pro', cell_ext);
+ var con = $('.con', cell_ext);
+
+ if (vote == 1 || vote == 0 && votedOther) pro.html('+' + (parseInt(pro.text().substr(1)) + (vote == 1 && !voted ? 1 : -1)));
+ if (vote == 0 || vote == 1 && votedOther) con.html('–' + (parseInt(con.text().substr(1)) + (vote == 0 && !voted ? 1 : -1)));
+
+
+ var wvote = $(this).closest('.wvote');
+ setTimeout(function() { $('.w-btn', wvote).removeClass('active'); }, 200);
+ setTimeout(function() { cell_ext.removeClass('active active-locked'); }, 1000);
+
+ $.getJSON('/api/photo/comment/rate', { action: 'vote-comment', wid: wvote.attr('wid'), vote: vote }, function (data)
+ {
+ if (data && !data[3])
+ {
+ $('.w-btn[vote="1"]', wvote)[data[0][1] ? 'addClass' : 'removeClass']('voted');
+ $('.w-btn[vote="0"]', wvote)[data[0][0] ? 'addClass' : 'removeClass']('voted');
+
+ pro.html('+' + data[1][1]);
+ con.html('' + data[1][0]);
+
+ setComVote(cell, data[2]);
+ }
+ else if (data[3]) alert(data[3]);
+ })
+ .fail(function(jx) { if (jx.responseText != '') alert(jx.responseText); });
+
+ return false;
+ })
+ // Отображение кнопок
+ .on('mouseenter mouseleave', '.w-btn[vote="1"]', function() { $(this).toggleClass('s2 s12'); })
+ .on('mouseenter mouseleave', '.w-btn[vote="0"]', function() { $(this).toggleClass('s5 s15'); })
+ .on('mouseenter touchstart', '.wvote', function() { $('.w-btn, .w-rating-ext', this).addClass('active'); })
+ .on('mouseleave', '.wvote', function() { $('.w-btn, .w-rating-ext', this).removeClass('active'); })
+ .on('touchstart', function(e) { if (!$(e.target).is('.wvote') && $(e.target).closest('.wvote').length == 0) $('.w-btn, .w-rating-ext').removeClass('active'); });
+
+
+ // Подсветка комментария, если дана ссылка на комментарий
+ var anchorTestReg = /#(\d+)$/;
+ var arr = anchorTestReg.exec(window.location.href);
+ if (arr != null) $('.comment[wid="' + arr[1] + '"]').addClass('s2');
+
+
+ // Ссылка на комментарий
+ $('.cmLink').on('click', function()
+ {
+ var comment = $(this).closest('.comment');
+ comment.siblings().removeClass('s2');
+ comment.addClass('s2');
+ });
+
+
+ // Удаление комментария
+ $('.delLink').on('click', function() { return confirm(_text['P_DEL_CONF']); });
+
+
+ // Цитирование
+ $('.quoteLink').on('click', function()
+ {
+ var comment = $(this).closest('.comment'), mText, mTextArray;
+ var selection = window.getSelection();
+
+ var selectedText = selection.toString();
+ var quotedText = (selectedText == '') ? $('.message-text', comment).text() : selectedText;
+ var msg = '';
+
+ if (selectedText == '' && comment.next('.comment').length == 0) msg = _text['P_QUOTE_MSG']; else
+ if (quotedText.length > 600) msg = _text['P_QUOTE_LEN'];
+
+ if (msg != '')
+ {
+ if ($('.no-quote-last', comment).length == 0) comment.append('' + msg + '
');
+
+ if (lastQuoteLinkBlock)
+ {
+ lastQuoteLinkBlock = false;
+ return false;
+ }
+ }
+ else $('.no-quote-last').remove();
+
+ if (selectedText == '')
+ mText = $('.message-text', comment).html();
+ else mText = $('').append(selection.getRangeAt(0).cloneContents()).html();
+
+ mText = mText.replace(/<\/?i[^>]*>/ig, '').replace(/<\/?u>/ig, '').replace(/<\/?span[^>]*>/ig, '').replace(/<\/?div[^>]*>/ig, '');
+ mText = mText.replace(new RegExp('\
[^>]*\<\/a\>', 'ig'), '');
+ mText = mText.replace(/
]+)>)/ig, '').replace(/\[br\]/ig, '
').replace(/</ig, '<').replace(/"e;/ig, '"').replace(/&/ig, '&');
+ mTextArray = mText.split(/
\s*/i);
+
+ var mText2 = '';
+ for (var i = 0; i < mTextArray.length; ++i)
+ mText2 += '> ' + mTextArray[i] + '\n';
+
+ var txtField = $('#wtext');
+ if (txtField.length)
+ {
+ var messageText = txtField.val();
+ var insertText = (messageText == '' ? '' : '\n') + _text['P_QUOTE_TXT'] + ' (' + $('.message_author', comment).text() + ', ' + $('.message_date', comment).text() + '):\n' + mText2 + '\n';
+
+ txtField.val(messageText + insertText);
+ txtField[0].focus();
+ }
+
+ return false;
+ });
+
+
+ // Отправка комментария
+ $('#f1').on('submit', function()
+ {
+ if ($('#wtext').val().trim() == '')
+ {
+ alert(_text['P_ENTERTEXT'] + '.');
+ return false;
+ }
+ else $('#sbmt').attr('disabled', true).val(_text['P_WAIT']);
+ });
+
+
+ // Окно ввода комментария
+ $('#wtext').on('keypress', function(e) { if ((e.which == 10 || e.which == 13) && e.ctrlKey) $('#f1').submit(); })
+ .on('focus', function() { navLock = true; })
+ .on('blur', function() { navLock = false; });
+
+
+ // Переключатель подписки
+ $('.toggle, .toggle-label').on('click', function(e)
+ {
+ if (e.target.tagName == 'A') return;
+ var toggle = $('.toggle').toggleClass('on');
+
+ $.get('/api.php', { action: 'subscribe', id: $('#id').val(), subj: $('#subj').val() }, function (r)
+ {
+ if (r != 0 && r != 1)
+ {
+ toggle.toggleClass('on');
+ alert(r);
+ }
+ else toggle.attr('class', (r == 1) ? 'toggle on' : 'toggle');
+ });
+ });
+});
\ No newline at end of file
diff --git a/views/components/LoadHead.php b/views/components/LoadHead.php
index ca418b7..216fa24 100644
--- a/views/components/LoadHead.php
+++ b/views/components/LoadHead.php
@@ -21,6 +21,7 @@
+
diff --git a/views/pages/Photo.php b/views/pages/Photo.php
index 2f9e755..79c89f4 100644
--- a/views/pages/Photo.php
+++ b/views/pages/Photo.php
@@ -21,7 +21,6 @@ $photouser = new \App\Models\User($photo->i('user_id'));
-=Vote::photo(Auth::userid(), $id)?>