HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptModerate

"The 2nd Monitor" chatroom translator

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thechatroommonitortranslator2nd

Problem

For those who go to The 2nd Monitor chatroom, you already know how bad I am at remembering everything. And, sometimes, the new visitors will wonder what something means.

For that, I've developed a very simple chat translator.

`;(function(window, undefined){
'use strict';

var memes = {
'zombie': {
'title': 'Unanswered question (or with answers without upvotes)',
'href': 'http://meta.codereview.stackexchange.com/a/1511/',
'find': new RegExp('(zombie)','gi')
},
'Jamalized': {
'title': 'Being Jamalized means that Jamal edited your question/answer',
'href': 'http://meta.codereview.stackexchange.com/a/1675/',
'find': new RegExp('(jamalized)','gi')
},
'TS': {
'title': 'Theoretical Star (star it and say "RSA")',
'href': 'http://meta.codereview.stackexchange.com/a/1526/',
'find': new RegExp('(TS)','g')
},
'RSA': {
'title': 'Real Star Applied (you say it after staring a message with "TS")',
'href': 'http://meta.codereview.stackexchange.com/a/1526/',
'find': new RegExp('(RSA)','g')
},
'Thanks, Santa!': {
'title': 'When someone upvotes a post, and you don\'t know who, just say this',
'href': 'http://meta.codereview.stackexchange.com/a/1526/'
},
'IWNPFETTOLAI': {
'title': 'I will not provide further explanation than this overly long acronym itself',
'href': 'http://meta.codereview.stackexchange.com/a/1673/'
},
'Monking': {
'title': 'A greeting to the Monkey doing his monkey-business',
'href': 'http://meta.codereview.stackexchange.com/a/1678/',
'find': new RegExp('(monk(?:ing|ernoon|evening|night))','gi')
},
'TTQW': {
'title': 'Time To Quit Work',
'href': 'http://meta.codereview.stack

Solution

And here I go:

-
Take advantage of the fact that SE sites use jQuery. This will trim down your DOM manipulation code to a high degree.

-
We usually have a rule in our team that the most you should nest for conditions is 2. If you have 3 or more nested, then it's time you use a function.

-
One problem I find problematic about nested if-else and other conditional blocks is that it's hard to trace what they changed. Try writing ala Functional Programming, where you call a function, pass in a value, and get a new value. Combine it with ternaries or hash maps and it ain't so bad.

-
I suggest against "one var for all vars" as it becomes hard to determine when the vars end and the real code starts. For instance, I tried cleaning your code, but the indent is off at first glance, then discovered the "one var".

-
Use "early return" if you happen to have if blocks with no else and nothing after it.

function foo(){
  if(bar){
    // code at second level
  }
}

// is the same as

function foo(){
  if(!bar) return;
  // code at first level
}


Now my jQuery is a bit rusty, but I think your logic can be simplified to the following. It may not be complete, but you get the idea.

setInterval(function translate() {

  // Look for a child element that is not .onebox from .content that's under a non-checked ancestor .message in #chat
  // Phew! That's a long one!
  $('#chat .message:not([data-checked="1"]) .content > :not(.onebox)').each(function(index, content){

    // Mark the ancestor .message as checked.
    // We use attr() instead of .data() because we're using a selector to look, and data() doesn't alter attributes
    $(content).closest('.message').attr('data-checked', 1);

    var contentChildren = $(content).children();

    // Looking for text nodes with jQuery filter
    contentChildren.filter(function(index, element){

      return element.nodeType === 3;

    }).each(function(index, element){

      var html = $(element).text();

      $.each(memes, function(key, meme){
        html.replace(meme.find || meme, '' + meme + ''); 
      });

      element.replaceWith(html);
    });
  });

}, 5000);

Code Snippets

function foo(){
  if(bar){
    // code at second level
  }
}

// is the same as

function foo(){
  if(!bar) return;
  // code at first level
}
setInterval(function translate() {

  // Look for a child element that is not .onebox from .content that's under a non-checked ancestor .message in #chat
  // Phew! That's a long one!
  $('#chat .message:not([data-checked="1"]) .content > :not(.onebox)').each(function(index, content){

    // Mark the ancestor .message as checked.
    // We use attr() instead of .data() because we're using a selector to look, and data() doesn't alter attributes
    $(content).closest('.message').attr('data-checked', 1);

    var contentChildren = $(content).children();

    // Looking for text nodes with jQuery filter
    contentChildren.filter(function(index, element){

      return element.nodeType === 3;

    }).each(function(index, element){

      var html = $(element).text();

      $.each(memes, function(key, meme){
        html.replace(meme.find || meme, '<a href="' + meme.href + '" title="' + meme.title + '">' + meme + '</a>'); 
      });

      element.replaceWith(html);
    });
  });

}, 5000);

Context

StackExchange Code Review Q#96724, answer score: 13

Revisions (0)

No revisions yet.