add link discussion after hit anchor in comment
This question is about a plugin i use from last year, original written by @hgtonight.
What it is about: in every comment appears an gray V which a user can click on. After clicking, the V becomes green. So a user can click on it when he/she decides that that comment was the best answer to his question. This all works fine.
What i want to achieve now is that when a V is marked green, there must be an anchor "echood" to the top of the Discussion with a permalink to that specific comment which has the green V
This is part of the code i already have:
protected function AddMarkV($Sender) { $Discussion = $Sender->EventArguments['Discussion']; $Session = Gdn::Session(); $Comment = $Sender->EventArguments['Comment']; if($Session->UserID == $Discussion->InsertUserID || $Session->CheckPermission('Garden.Moderation.Manage')) { if ($Comment->MarkV) { //echo Anchor("", 'discussion/markv/' . $Comment->CommentID, 'Hijack img-swap on'); echo Anchor("", 'discussion/markv/' . $Comment->CommentID, array('title' => "Annuleren", 'class' => "Hijack img-swap on")); } else { //echo Anchor("", 'discussion/markv/' . $Comment->CommentID, 'Hijack img-swap'); echo Anchor("", 'discussion/markv/' . $Comment->CommentID, array('title' => "Beste Antwoord", 'class' => "Hijack img-swap")); } } else { if ($Comment->MarkV) { echo Wrap("", 'div', array('class' => 'Hijack img-swap on')); $Sender->CommentModel->SetField($Comment->CommentID, 'MarkV', !$Comment->MarkV); } else { echo Wrap("", 'div', array('class' => 'Hijack img-swap')); } } }
When hitting the V, the background of the class changes and the V becomes green. So it is only a class change.
This is what i am experimenting with so that the Link to the green V comment appears before the first comment in the discussion (so just below the topic start-comment). But i get stuck on it and i need some help with it:
///////////////////////////////in development ///////////////////////////// public function DiscussionController_BeforeCommentDisplay_Handler($Sender) { //this place is between topic start and first comment //$Permalink = '/discussion/comment/'.$Comment->CommentID.'/#Comment_'.$Comment->CommentID; $Permalink = GetValue('Url', $Comment, '/discussion/comment/'.$Comment->CommentID.'/#Comment_'.$Comment->CommentID); if ('class' => "Hijack img-swap on") { // if the green V is hit echo Anchor(T('Linktext'), $Permalink, 'Permalink', array('name' => 'Item_'.($CurrentOffset), 'rel' => 'nofollow')); // echo this anchor to the top of the discussion } } ////////////////////////////////////////////////////////////
Comments
As far as I understand this, the info which comment is marked is only stored in the specific comment, correct? If that's so, you would have to loop through all comments in order to find out the correct link.
I would recommend that you store the information about the "MarkV.CommentID" in the discussions attributes. There are some methods for that in the model: http://vanillaforums.org/discussion/comment/233096/#Comment_233096
I think you should use
public function saveToSerializedColumn($Column, $RowID, $Name, $Value = '')
like that:In
DiscussionController_AfterDiscussion_Handler
you should be able to access this info with $CommentID = $Discussion->Attributes['MarkV.CommentID'], build a link based on that and display it.I'm not 100% sure about that
$Discussion->Attributes['MarkV.CommentID']
, but if you do adecho($Discussion->Attributes);
it should become obvious on how to access that info.P.S.: don't you want to replace "V" with
✅
=> ✅✓
=> ✓✔
=> ✔or even
👌
=> 👌💡
=> 💡💋
=> 💋Unicode is so cool!
I now have this create and the link appears after a refresh when clicked on the V:
I created a new public function:
And now i add this function to the DiscussionController (BeforeCommentHeading):
The problem: the link does not appear before the first comment (which should be because BeforeCommentHeading is that place)
When i change it to:
public function DiscussionController_BeforeCommentDisplay_Handler($Sender) {
the testlink does appear but at the wrong place ofcourse.
Don't know why
public function DiscussionController_BeforeCommentHeading_Handler($Sender) {
does not show the linkYou could always test if your function is called by inserting something like
decho(__LINE__);
In this case I would assume it is not called because that is never used as an event: https://github.com/vanilla/vanilla/search?utf8=✓&q=BeforeCommentHeading
Try the plugin eventi to find out the events your can use. But don't use that plugin in production.
Well, i tried to find out the fireEvent and i did compare it with Voting plugin.
This is where the sorting tabs are echood in Voting:
In markV plugin i have this code:
This is the result:
You can see in both plugins, the code is in DiscussionController_BeforeCommentDisplay_Handler; but they appear in the Voting plugin on the correct place and in the MarkV plugin on the wrong plaace (above user icon)
What am i doing wrong?
In such a case you should do two things:
1. look at the code that fires the event in order to know what markup is expected and
2. check the rendered html if the output has the desired markup
Look at https://github.com/vanilla/vanilla/blob/release/2.1/applications/vanilla/views/discussion/helper_functions.php#L77-L78 and you will see that the next line after the event starts with a li tag so obviously this event is fired in an unordered list. Your output must be enclosed in li tags to generate valid html.
I now get stuck on the markV condition.
I show 3 situations what happens.
See below:
Snap1:
Snap2:
Snap3:
This is the code:
So the situation what happens:
If i echo only TESTLINK without the condition if ($Comment->MarkV) { on line 8 above, the TESTLINK appears in CommentHeading area.
If i put the TESTLINK echo in the condition, TESTLINK is gone in CommentHeading area.
If i change public function DiscussionController_CommentHeading_Handler($Sender) { to public function DiscussionController_BeforeCommentDisplay_Handler($Sender) { with the condition and clicked on 2 green V, the 2 TESTLINKS are visible but at the wrong place ofcourse.
But these TESTLINKS should appear in CommentHeading ! Seems not possible? What am i doing wrong?
not closely following, but if you can't get something positioned as you wish with one type of event, you can always choose a different event and position things.
Perhaps pick a suitable event that displays the items correctly as far as visibility in all cases you need it and then use css positioning to move it to correct place.
http://www.w3schools.com/css/css_positioning.asp
I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.
@peregrine Yes that is also possible, i know. But i was wondering if this is not possible what i am trying to achieve or am i doing something wrong?
It mightbe possible, but I'm also unsure what you try to achieve...
Generally:
When something in a condition is not shown, although you expect it, the condition is not met
So if you would swear that a=b but the code in
if ($a == $b) {...}
is not executed, try adecho($a); decho($b);
.If I stumble upon code that behaves not like I expect it, I add numerous
decho(__LINE__);
right before if conditions and loops and inside o them just to see what is really executed and what is not.Another thing you should do when you expect that there must be an output but you cannot see it: look at the html source. Because you might run into styling issues and therefore your output might be hidden.
In your case:
BeforeCommentDisplay
is fired between comments. So semantically, I wouldn't add any comment related info there. You are right in the unordered list of all comments, so semantically whatever you put there has the character of a comment. I could not think of a anything to echo there. Instead of this, I would only use it to change one of the EventArguments, but that is not your intention here.Back to the problem:
We haven't really understood what you want to do. You have said "This is what i am experimenting with so that the Link to the green V comment appears before the first comment in the discussion (so just below the topic start-comment)"
Looking at it right now seems to explain why we cannot help you and you get surprised by the results of what you are doing.
So what you think you are doing right now is: you loop through all comments and if there is a marked comment, you write some html with the help of any event at the top of the comment list, correct?
What I know you are doing is that those events are called for every comment. So you are already in the loop of comments when the event is fired. If you want to show something right before the start of all comments you must find that event. The events you are trying are all fired inside of the
WriteComment
function. This function writes the markup for each single comment. So if you try to take influence on what is written before the very first one, this is not the right place to look.So if you look for the right place to echo markup you have to understand the structure of Vanilla. You have to inspect the view that Vanilla uses for rendering a discussion. Et voilà! Look at
applications/vanilla/views/discussion
. Okay here is more than one file. But what file is always the default file on the good old internet? The index file! So take a look atindex.php
and you'll find the html structure of a discussion.You can call
AfterDiscussion
to add info that is discussion related because it is called right before the<div class="MessageList Discussion">
closes.You can also use
CommentHeading
but looking at the code I'd say that you would have styling problems because that seems to be enclosed from paginating markup.So try DiscussionController_AfterDiscussion! And that is the place where you have to loop through all comments to find the one which MarkV == true.
Better than looping through all comments would be store the MarkVCommentID in the discussion attributes, so that you directly access it.
You seem to be right @R_J
I put an else in the loop (line 24 below)
This is what happens when i use DiscussionController_BeforeCommentDisplay_Handler
And this is what happens when i use DiscussionController_AfterDiscussion_Handler
This behaviour explains to me that in BeforeCommentDisplay event he looks if MarkV is clicked and then shows the TESTLINK for that Comment ID (because it met the condition)
In AfterDiscussion event he checks not on the Comment ID anymore and if only 1 markV is not clicked, then it does not met the condition anymore and the NOT MET CONDITION appears