Using color to organize threaded comments with javascript

02.23.2014

Threaded comments are pretty neat and having that little indentation for each comment provides a bit of visual context of who is talking to whom. But, it can get difficult to figure it out sometimes.

Here's what I'm talking about:

Screen Shot 2014-02-21 at 12.36.55 PM

Now let's try drawing a border for child comments.

children-with-borders

That's a big improvement! There's a problem though, the lines only tell whether a comment is nested or not and you can't infer which thread the comment comes from without counting the lines. That's extra work we shouldn't make our users do.

So, how about adding some color?

comment-children-with-color

There we go. Now we have two pieces of information: how deep a comment is nested and from which thread the comment belongs to from just a single line. Demo here. You can view the source on Github.

Implementation

For the sake of demonstration, I'm going to use Javascript to style the comments. But this can easily be done on the backend. The important thing to realize is that threaded comments are a tree. The code is down below and let's assume that each comment has a class "comment" and in a div with id "holder".

Deciding which colors to use - We're going have a stack (kind of) filled with colors and we're going to push a new color when we enter a child and pop when we're done and going to back to the parent. By doing it this way we don't need to know which level we're on, we just push and pop on our stack.

var colorStack = {
         // There is a color for each level, when
         // we run out, we roll over. Add more colors as needed.
	 colors : [
		"#33B5E5",
		"#FF4444",
		"#FFBB33",
		"#AA66CC",
		"#99CC00",
	],

	index : -1,
	push : function () {
		this.index = ( this.index + 1 ) % this.colors.length;
	},
	
	pop : function () { 
		this.index = this.index - 1 > 0 ? this.index - 1 : 0;
	},

	getColor : function () {
		return this.colors[this.index];
	}
};

Assigning colors - The basic idea is we're going to go through the list of children and if that child has a family, we go through its children and so and so on. For each level we visit, we pick a different color.


function colorize (root) {
	var $children = $(root).children('.comment');
	for (var i = 0; i < $children.length; i++) {
                
                // This assumes that the comments have a border-width and
                // border-style set already.
		$($children[i]).css( { 'border-left-color' : 
                                        colorStack.getColor() });

                // If this child has children, we recurse passing this child as
                // the root of our new subtree
		if(  $($children[i]).children('.comment').length > 0 ) {
                        // We give a new color for this family
			colorStack.push();

			colorize($children[i]);

                        // And we need to make sure we undo it when
                        // we go up a level.
			colorStack.pop();
		}
		
	};
}

// Call it like this, where the argument is the root of the comment tree.
colorize($("#holder"));