27

I would like to be able to click on a comment and see replies to that user highlighted in the comment thread.

This would be especially helpful in longer meta discussions, but I can see it working well on the main sites too.

I'm aware that the conversational flow is impossible to programmatically understand. So I'm simply suggesting that when you click on a comment made by foo, all messages containing @foo will be highlighted.

Below is an example of what I'm talking about. Here I've clicked on the comment from hichris123. The selected comment is ringed in colour, with the replies to that user highlighted beneath.

example of highlighting

I used Rene's user script to produce this screenshot

  • 4
    That's an excellent idea for userscript - surely someone will jump on the wagon soon and write one. ;) – ShaWiz Mar 12 '15 at 9:04
  • 3
    might be useful; I would actually also highlight all further comments by the same user as well (in a different color). Or,alternatively, highlight only their name, whether it occurs after an @ or as the author of the comment – HugoRune Mar 12 '15 at 9:24
  • @HugoRune That feels a little over-complicated to me, but it would be interesting to see what others think. I tried to keep the goals of this feature request pretty simple – Duncan Jones Mar 12 '15 at 12:30
  • 3
    I say it should get implemented, as there seems to be no disadvantage of doing so. – ghosts_in_the_code Mar 12 '15 at 17:26
  • I hope if Jin could see this and implement it in the next release. :) – user280850 Mar 12 '15 at 17:27
16

Ok, until this gets implemented here is a user script to do that:

// ==UserScript==
// @name         Comment thread highlighter
// @namespace    http://meta.stackexchange.com/users/158100/rene
// @version      0.5
// @description  Higlight where OP is @mentioned
// @author       rene
// @match        *://*.stackexchange.com/questions/*
// @match        *://stackoverflow.com/questions/*
// @match        *://meta.stackoverflow.com/questions/*
// @grant        none
// ==/UserScript==

/*global $, unsafeWindow */

(function ($) {
    "use strict";
    var cc = $('div#mainbar'),
        color = '#CCFFCC',
        marker = 'data-comment-highlight';

    /* return the number of characters that match
       in a given string from a specific position
       ('@foobar comment', '@foo', 0, 7) -> 4
    */
    function matchCount(words, find, pos, len) {
        var t = 0,
            cnt = 0;
        for (t; t < len &&
                (pos + t < words.length) &&
                (words[pos + t] === find[t]);
                t = t + 1) {
            cnt = cnt + 1;
        }
        return cnt;
    }

    /* return the highest number of characters
       that match if find is searched for in words
    */
    function findAt(words, find) {
        var best = 0,
            i = words.indexOf('@'), // '@foo comment' ->0  'my@email.com' -> 2 'comment @foo' -> 8
            space;
        if (i > 0) {
            i = words.indexOf(' @', i - 1); // 'my@email.com' -> 0  'comment @foo' -> 8
        }
        while (i > -1) {
            space = words.indexOf(' ', i + 1);
            if (space === -1) {
                space = words.length;
            }
            // require at least 4 chars for a match
            if (space - i > 3) {
                best = Math.max(
                    matchCount(words, find, i, space - i),
                    best
                );
            }
            i = words.indexOf(' @', space);
            i = i + (i > -1 ? 1 : 0);
        }
        return best;
    }

    function buildAtUser(author) {
        var  mod = author.find('span').text(); // moderator diamond
        // remove spaces and remove the diamond
        return '@' + author.text().replace(' ', '').replace(mod, '');
    }

    /* subscribe to click higher in the dom to let this work
    when new comments gets loaded as well.
    */
    cc.on('click', 'span.comment-copy', function (e) {
        var target = $(e.target),
            src = target.closest('tr'), // comment row
            tbody = target.closest('tbody'), // all comments for the post
            at = buildAtUser(target.parent().find('a.comment-user')), // find this
            remove = src.hasClass(marker),
            found = false;


        tbody.find('tr.comment').each(function () {
            var tr = $(this),
                cmt = tr.find('span.comment-copy').text(),
                match = findAt(cmt, at); //find user in this comment

            // more than 1 chars is a match
            if (match > 1) {
                found = true;
                if (remove) {
                    tr.css('background-color', '');
                } else {
                    tr.css('background-color', color);
                }
            }
        });
        // only set our src once
        if (found) {
            if (remove) {
                src.removeClass(marker);
                src.css('border', '');
            } else {
                src.addClass(marker);
                src.css('border', color + ' solid');
            }
        }
    });
}($ || unsafeWindow.$));

If you click on a comment this script finds the author. It then walks-up the DOM to find the table body it is in and then find all comment table rows. Inside each row it finds the comment-copy and with a simple indexOf determines if the author is @-mentioned there. If so it sticks a background-color on the tablerow. You click the comment again to remove the highlighting.

New in version 0.5 is matching partial usernames and also works for comments that are loaded after clicking load more comments, code jslinted

This is tested in Chrome with TamperMonkey but should work in Firefox GreaseMonkey as well.

  • I just had a little play with this (Chrome/TamperMonkey), and it seems like a great start! It would be nice if the comment I clicked was ringed in colour too. And I think it would be better if the highlighting remained until I clicked elsewhere, but I appreciate you're not my code monkey! – Duncan Jones Mar 12 '15 at 9:38
  • The comment clicked gets a border now as well. The feature to click again to dismiss the highlighting troubles me a little bit, specially the clicked elsehwere. Maybe when you clicked on the same comment again to dismiss might be doable. – rene Mar 12 '15 at 9:48
  • "Maybe when you clicked on the same comment again to dismiss might be doable" That would certainly be preferable to having it disappear after a few seconds. The yellow is a little garish too ;-), looks nice with #CCFFCC. Also, it probably needs to remove spaces from the username to match, e.g., Shadow Wizard vs @ShadowWizard. – Duncan Jones Mar 12 '15 at 9:52
  • @Duncan done the color, fixed the username with spaces thingy and added the toggle functionality. – rene Mar 12 '15 at 11:03
  • Excellent! This will certainly suffice until the functionality appears in the site (if at all, of course). Maybe you should move this to stackapps.com so that we can continue to discuss it? This answer could then be edited to simply point to that. – Duncan Jones Mar 12 '15 at 11:04
  • This could be extended to: @match *://*.stackoverflow.com/questions/*. to ensure Meta Stack Overflow is covered. – Duncan Jones Mar 17 '15 at 8:54
0

I disagree with this suggestion. It encourages having such threaded conversations in the first place, which you shouldn't be doing in comments. Do it in chat, instead, which already highlights reply-threads.

  • I don't see how highlighting things adds any functionality to comments. Would you prefer if the highlighting ceased after the next time the commenter comments? – Duncan Jones Mar 18 '15 at 6:28
  • @Duncan: I'm saying that there should not be highlighting in comments. Making it easier to have conversations in comments will encourage people to have conversations in comments, despite the fact that people should not be having conversations in comments. It's really as simple as that. – Lightness Races in Orbit Mar 18 '15 at 10:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .