2
\$\begingroup\$

I made a tumbler thingy...
Do you see possible bugs in the code or any improvements I could do?

var text = "0000 ASCII (Listeni/ˈæski/ ass-kee), abbreviated from American Standard Code for Information Interchange,[1] is a character-encoding scheme (the IANA prefers the name US-ASCII[2]). ASCII codes represent text in computers, communications equipment, and other devices that use text. Most modern character-encoding schemes are based on ASCII, though they support many additional characters. ASCII was the most common character encoding on the World Wide Web until December 2007, when it was surpassed by UTF-8, which includes ASCII as a subset.[3][4][5]";

// Returns a random integer between min and max.
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function tumbler(text) {
  var length = text.length;
  var tumbleText = "";

  function tumble() {
    var code, i, newTumbleText = "",
      rand;

    // Test if we're done.
    if (text === tumbleText) {
      return document.body.style.color = "white";
    }

    for (i = 0; i < length; i++) {
      // Compare the two chars.
      if (text[i] !== tumbleText[i]) {
        code = text.charCodeAt(i);
        rand = getRandomInt(code - 10 < 0 ? 0 : code - 10, code + 10);
        newTumbleText += String.fromCodePoint(rand);
      } else {
        newTumbleText += text[i];
      }
    }

    tumbleText = newTumbleText;
    document.body.textContent = tumbleText;
    window.setTimeout(tumble, 60);
  }

  tumble();
}

tumbler(text);
body {
  background: black;
  color: lime;
  font-family: Courier, monospace;
}

\$\endgroup\$
  • \$\begingroup\$ The demo would be so much cooler if it were in a monospace font. \$\endgroup\$ – 200_success Feb 23 '16 at 21:13
  • \$\begingroup\$ @200_success I made one that does the entire page jsFiddle (just paste it in console). Let's try monofont next indeed ;) \$\endgroup\$ – Jonathan Feb 23 '16 at 21:30
1
\$\begingroup\$

Repeated string concatenation is not recommended, since strings are immutable. You should use an array of characters instead, and perform one join at the end.

Since your random number generator is not really retrieving anything, I'd rename getRandomInt() to just randomInt(). I would hide the function as a helper inside the tumbler() function. The convention in JavaScript is to use inclusive lower bounds and exclusive upper bounds. (See String.substring(start, end), for example.) To establish the lower bound for the call, I would use Math.max() instead of the ternary expression.

I don't like to see lots of variable declarations up front, especially when I have no idea what these variables mean.

var code, i, newTumbleText = "",
  rand;

It would be better to declare them at the point of use, and use 'use strict' to ensure that all variables are properly declared.

If you use font-family: monospace and ensure that spaces are preserved rather than randomized, then the animation would look less erratic.

var text = "0000 ASCII (Listeni/ˈæski/ ass-kee), abbreviated from American Standard Code for Information Interchange,[1] is a character-encoding scheme (the IANA prefers the name US-ASCII[2]). ASCII codes represent text in computers, communications equipment, and other devices that use text. Most modern character-encoding schemes are based on ASCII, though they support many additional characters. ASCII was the most common character encoding on the World Wide Web until December 2007, when it was surpassed by UTF-8, which includes ASCII as a subset.[3][4][5]";
tumbler(text);

function tumbler(text) {
  'use strict';
  var buffer = new Array(text.length);
  tumble();

  // Returns a random integer between min (inclusive) and max (exclusive).
  function randomInt(min, max) {
    return Math.floor(Math.random() * (max - min)) + min;
  }

  function tumble() {
    var done = true;
    for (var i = 0; i < buffer.length; i++) {
      if (text[i] === ' ') {
        buffer[i] = ' ';
      } else if (text[i] !== buffer[i]) {
        var code = text.charCodeAt(i);
        var rand = randomInt(Math.max(0, code - 10), code + 11);
        buffer[i] = String.fromCodePoint(rand);
        done = false;
      }
    }
    
    if (done) {
      document.body.style.color = "white";
    } else {
      document.body.textContent = buffer.join('');
      window.setTimeout(tumble, 60);
    }
  }
}
body {
  background: black;
  color: lime;
  font-family: monospace;
}

\$\endgroup\$
  • \$\begingroup\$ Thanks, I'll take a look tomorrow. Here's a bookmarklet version of this effect for your troubles ;) \$\endgroup\$ – Jonathan Feb 23 '16 at 23:24
  • \$\begingroup\$ Nice changes you did there. The buffer and Math.max are much better indeed, and I also like the optimization you did to done. Bonus points for keeping the spaces, it looks better. \$\endgroup\$ – Jonathan Feb 24 '16 at 18:42
1
\$\begingroup\$

Pretty fun little bit of code. Very neatly written as well. Only thing I would suggest would be to use .charAt(x) instead of using array indexers for your strings when you're comparing characters. Not a big deal but will improve compatibility among browsers and is a bit easier to read IMHO.

// Compare the two chars.
if (text.charAt(i) !== tumbleText.charAt(i))

Good stackoverflow post covers it in more detail here.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.