Upvote / Downvote Function On Topic Level
-
@baris sorry, still kinda new to this. Correct me if I'm wrong, but I think votes.js is looking for the closest data-pid and not data-mainPid in the template right? Here's my current code and I'm sure I'm missing a lot of stuff here:
<div class="col-md-1 hidden-xs hidden-sm total-post-votes" data-pid="{topics.mainPid}"> <a component="post/upvote" href="#" class="<!-- IF posts.upvoted -->upvoted<!-- ENDIF posts.upvoted -->"> <i class="fa fa-chevron-up"></i> </a> <div title="{topics.votes}">{topics.votes}</div> <!-- IF !downvote:disabled --> <a component="post/downvote" href="#" class="<!-- IF posts.downvoted -->downvoted<!-- ENDIF posts.downvoted -->"> <i class="fa fa-chevron-down"></i> </a> <!-- ENDIF !downvote:disabled --> </div>
In order to read the closest data-pid on upvote/downvote, do I need to create a custom js function for that?
-
@Teemberland Yes since what you are doing isn't supported by core, you need some custom JS that runs when the user clicks the upvote/downvote buttons on the topic list. In that custom JS code you need to get the closest pid(which is the mainPid of the topic) and then make the API call.
-
@baris for custom JS. Where is the best place to add it?
-
@baris I think I'm close. I just need to know how I can pass in 'delta' in my custom js (I believe delta is required in upvote/downvote)
https://github.com/NodeBB/NodeBB/blob/master/public/src/client/topic/votes.js#:~:text=api[method](%60/posts/%24%7Bpid%7D,%7D
var pid = $(this).closest('.total-post-votes').find('.tl-upvote').attr('data-pid'); var method = $(this).closest('.total-post-votes').find('.tl-upvote').hasClass('upvoted') ? 'put' : 'del'; api[method]('/v3/' + '/posts/' + pid + '/vote').then(() => { delta: delta, });
Let me know if this is incorrect though. I'm not sure if I should call toggleVotes from the client side.
-
This post is deleted!
-
@baris the following code is working, however, the upvoted class is not persisting when I navigate to another page, like for instance when I click the topic and go back to topic list, the class disappears.
Also, when I do upvote, I can see the first post being upvoted, but the vote number is not changing onclick. The page has to reload to see the vote number.
function topicVotes() { $(window).on('action:ajaxify.end', function () { require(['api'], function (api) { $('.tl-upvote').closest('.total-post-votes').find('.tl-upvote').on('click', function () { var pid = $(this).attr('data-pid'); var method = $(this).hasClass('upvoted') ? 'put' : 'del'; api[method](`/posts/${pid}/vote`, { delta: 1, }).then(() => console.log('voted')); $(this).toggleClass('upvoted'); }); }); }); }
I apologize in advance, maybe I'm not understanding the client-side hooks just yet.
-
To make those work you need to code them as well.
When the post is voted either up or down you need to change the value in the DOM.
As for the
upvoted
class you need to update the topic_list.tpl template and add the class if the topic is already voted. Since that data isn't available in core you need to use a hook likefilter:topics.get
and add aahasUpvoted
field to each topic. -
If you want it to be only visible on a certain category, you will need to add a conditional in the topic_list.tpl. For example
{{{ if (template.category && (cid == "3")) }}} Display only on /category page and category id is 3 {{{ end }}}
The values used in the conditionals come from
ajaxify.data
you can see them in your browser when you load a category page. It is the same data you get when you visit/api/category/3
-
-
-
-