BE Comments vs Disqus

Topics: Themes
Jan 26, 2011 at 8:19 PM

Both comment systems are good, but I want to avoid the overhead of using disqus and going third party when the BE system does nicely.

However, in disqus when a moderator answers a comment a star with tooltip appears beside the commenters name indicating it's moderator - a useful touch.

I was wondering how to replicate this in BE (there will be multiple authors), my knowledge of DOT NET is miniscule, but here is what I came up with:

Function added to theme commentView.ascx minus the script tags.

protected bool canMod()
{      
    foreach(string user in Roles.GetUsersInRole("Editors"))
    {
        if (user.Equals(Comment.Author, StringComparison.OrdinalIgnoreCase))
        {
            return true;
        }             
    }
    return false;
}

Use the function to check if the commenter happens to be a user with editor rights and if so then apply suitable markup to indicate it's a moderator.

The problem is that the user name entered in the comments has to be just right, matching BE user name, is there a better way to accomplish this?

 

Coordinator
Jan 27, 2011 at 6:31 AM

If you look at the Standard theme's CommentView.ascx, for example, it actually has something where it compares the Post's Author to the Comment's Author, and if it's a match, it then outputs an extra CSS tag ("self") to the outer DIV.  It looks like this:

<div id="id_<%=Comment.Id %>" class="vcard comment<%= Post.Author.Equals(Comment.Author, StringComparison.OrdinalIgnoreCase) ? " self" : "" %>">

It's sort of non-ideal, but when you leave a comment in BE, and you enter the "Name" field, if you are logged out and you enter the same name as the post's Author, it disallows you from saving the comment (you'll get a validation error message).  Because this logic exists, it's basically guaranteed that the above markup will work ... since the only time a commenter's Name will equal the blog Post Author's name is when the commenter is logged into the blog and enters the same name in the Name field that is tied to the Post's author field (which is the same name that the person logs into the blog under).

As the editor/author, for the "self" CSS class to work, you do need to make sure that you're logged in and enter the same name into the comment field's Name field, so it matches the Post author.

With the extra CSS class "self" on the DIV, you can optionally style the DIV differently using CSS.  I've seen some pretty creative examples where someone floats the gravatar on the right side VS the left side when the "self" CSS class is there, among other things.

... btw, your code seems like it would work and accomplish the same thing.  It works a little differently than what I put here, but basically the same thing.

Jan 27, 2011 at 12:04 PM

Thanks Ben,

That was well explained, I noticed the validation error message on comment author = post author when testing and was wondering what was going on.

I did have a look at the code to compare comment and post author (nice), that's what got me thinking about doing something similar with moderators, lets say there are 3 moderators (class them as having editor roles) and at any time they can answer a comment on any post, it would be good to indicate moderator status or indeed post author if that's the case.

One of the problems with the way I was going about this is that I was not checking to see if a commenter who is not a moderator happens to have the same user name as a moderator, perhaps I could use the same validation logic that compares post and comment author to check this (now that I know it's there).

Then swap user name with profile displayName if it exists, add something like brackets moderator and show that on the comment instead of the user name. The CSS self tag is definitely a good idea, although it suits me to apply it more specifically than the vcard grouping with nested comments.

The other option I was thinking about was enforcing a specific format on user names and checking for that format, this would have the added benefit of ensuring the user name was URL friendly. I am passing author names around and spaces and such like are problematic.

For example, when you click on a post author name, it takes you to a listing with all their posts, I'm using the author name from the URL to grab details from the author profile to display a picture and bio before the listing - the user name has to be URL safe.

This is spiralling, my brain hurts.

 

Jan 27, 2011 at 12:59 PM

Just been poking around a little more, I was curious to see if any logged in user could comment as the post author and it seems they can.

So that means in a multi-author environment that author x could impersonate author y if they have a mind to, I know this is unlikely to happen, but when sussing something out I like to attack it from all angles.

Hope I'm not being too picky, I wouldn't be digging around like this if I didn't think it was worth the effort.

Jan 27, 2011 at 9:43 PM

Taking into account what Ben said about commenter = post author, here is the latest, it may be of interest to others.

Screen shot at http://www.mobiletvworld.com/exComments.html

The logic to reject commenters not logged in trying to use an existing moderators user name remains to be added, but here is the code for the rest.

<%@ Control Language="C#" EnableViewState="False" Inherits="BlogEngine.Core.Web.Controls.CommentViewBase" %>

<script language="C#" type="text/C#" runat="server">

protected string cSite, cName, cLinkName, cTagline; //vars for commenter details

protected void canMod()
{      
    cName = Comment.Author; //supplied commenter name
    cTagline = "";     
    foreach(string user in Roles.GetUsersInRole("Editors")) //check and see if the commenter is actually a moderator
    {                
        if (user.Equals(Comment.Author, StringComparison.OrdinalIgnoreCase))
        {
            string dName = AuthorProfile.GetProfile(user).DisplayName; //see if there are profile details
            if(!String.IsNullOrEmpty(dName)) //try and use display name
            {
                cName = dName;
            }               
            cTagline = "(Moderator) ";           
            cSite = AuthorProfile.GetProfile(user).PhoneFax; //PhoneFax field acts as surrogate for URL field
            break;          
        }             
    }
    //the commenter may or may not be a moderator but could be the post author
    if(Post.Author.Equals(Comment.Author, StringComparison.OrdinalIgnoreCase))
    {               
        cTagline = "(Author) ";
    }   
         
    if(Comment.Website != null) //supplied link takes precedence if given
    {
        cLinkName = "<a href=\"" + Comment.Website + "\" rel=\"nofollow\" >" + cName + "</a>";
    }
    else if(!String.IsNullOrEmpty(cSite)) //else use profile URL if present
    {
        cLinkName = "<a href=\"" + cSite + "\" rel=\"nofollow\" >" + cName + "</a>";
    }   
    else
    {
        cLinkName = cName; //it's not a linked name
    }   
}

</script>

<div id="id_<%=Comment.Id %>" class="vcard" >
    <div class="commentHdrContainer">
        <div class="commentHdr">                       
            <%= ReplyToLink %>               
            <div class="commentHdrLeftCol">
                <%= Gravatar(28)%>           
            </div>
            <div class="commentHdrRightCol">
            <% canMod(); %>
            <%= Flag %>&nbsp;<span class="commentAuthor">&nbsp;<%= cLinkName %></span>&nbsp;<%= cTagline %>&nbsp;<%= Comment.DateCreated.ToString("d MMM yyyy 'at' HH:mm")%> <a href="#id_<%=Comment.Id %>">#</a>
            </div>
        </div>
    </div>
    <div class="comment-text"><%= Text %></div>
    <%= AdminLinks.StartsWith(" | ") ? AdminLinks.Substring(3, AdminLinks.Length - 3) : AdminLinks %>
    <div class="comment-replies" id="replies_<%=Comment.Id %>" <%= (Comment.Comments.Count == 0) ? " style=\"display:none;\"" : "" %>>
        <asp:PlaceHolder ID="phSubComments" runat="server" />
    </div>
</div>

Jan 29, 2011 at 1:43 AM

Validation logic for commenters not logged in trying to use an existing moderators user name, this involves changing code outwith theme.

In file CommentView.ascx in the User controls folder add this just before function registerCommentBox()

<script language="C#" type="text/C#" runat="server">
protected static string getModerators()
{        
    string userNames = ""; //string to contain space separated moderator user names
    foreach(string user in Roles.GetUsersInRole("Editors")) //editors choosen as moderators, could be admin role, your choice
    {                
       userNames += user + " ";
    }
    return userNames.Substring (0, userNames.Length-1); //remove trailing space
}
protected static string modUserNames = getModerators();
</script>

Then within the function registerCommentBox() add the following line:

BlogEngine.comments.modNames = "<%=modUserNames %>";

 

Next you will need to make changes in your blog script located in the Scripts folder.

Find the line starting with  comments: {

Add replace that section with this:

 comments: {
        flagImage: null,
        contentBox: null,
        moderation: null,
        checkName: null,
        modNames:null,
        postAuthor: null,
        nameBox: null,
        emailBox: null,
        websiteBox: null,
        countryDropDown: null,
        captchaField: null,
        controlId: null,
        replyToId: null
    }

Then, in the same file...

Replace validateAndSubmitCommentForm: function () with this amended function :

There will be commas before and after in the existing code, make sure you leave these in place.

 validateAndSubmitCommentForm: function () {
        var bBuiltInValidationPasses = Page_ClientValidate('AddComment');
        var bNameIsValid = BlogEngine.comments.nameBox.value.length > 0;
        document.getElementById('spnNameRequired').style.display = bNameIsValid ? 'none' : '';
        var bAuthorNameIsValid = true;
        var bModNameIsValid = true;
        if (BlogEngine.comments.checkName) {
            var author = BlogEngine.comments.postAuthor;
            var visitor = BlogEngine.comments.nameBox.value;
                        var moderator = BlogEngine.comments.modNames;
                        if(moderator != null) {
                            var mNames = moderator.split(" ");
                            for(var i = 0, j = mNames.length; i < j; i++){
                                if(this.equal(mNames[i], visitor)) {
                                    bModNameIsValid = false;                                   
                                    break;
                                }
                            }                           
                        }
            bAuthorNameIsValid = !this.equal(author, visitor);
        }
        document.getElementById('spnChooseOtherName').style.display = bAuthorNameIsValid && bModNameIsValid ? 'none' : '';
        if (bBuiltInValidationPasses && bNameIsValid && bAuthorNameIsValid && bModNameIsValid) {
            BlogEngine.addComment();
            return true;
        }
        return false;
    }

Why do this?

It means that you can elect to have a group of users with a given role to act as comment moderators and when they login and post a comment reply it will automatically show up that they are moderators or post author.

 

Coordinator
Jan 29, 2011 at 10:07 AM

Thanks for sharing this code -- it looks good, and seems like you have a great handle on the process as well.