8
\$\begingroup\$

I am currently building a web app where I need to randomly switch the font and color of a title (inside the #content div) and the background of the page every time a button is clicked.

I wrote the following code that works perfectly, but I'm wondering if it could be optimized (or at least written in a more elegant way).

// Switch font randomly
var font = ["lobster", "shadows", "oswald", "josefin", "gloria", "pacifico"];
var color = ["blue", "purple", "yellow", "red", "orange", "green"];
var background = ["bg-blue", "bg-purple", "bg-yellow", "bg-red", "bg-orange", "bg-green"];
$("#try-me").click(function() {
 $("#content")
 .hide()
 .removeClass()
 .addClass(font[Math.floor(Math.random()*font.length)]) // Font
 .addClass(color[Math.floor(Math.random()*color.length)]) // Color
 .fadeIn(600);
 $("html")
 .removeClass()
 .addClass(background[Math.floor(Math.random()*background.length)]); // Background
});
rolfl
98.1k17 gold badges219 silver badges419 bronze badges
asked Aug 12, 2014 at 12:57
\$\endgroup\$
3
  • 1
    \$\begingroup\$ It's pretty clear and elegant as it is. \$\endgroup\$ Commented Aug 12, 2014 at 13:14
  • \$\begingroup\$ I agree with Carlos, looks clear and elegant as it is. \$\endgroup\$ Commented Aug 12, 2014 at 14:31
  • 1
    \$\begingroup\$ Perhaps you should ensure that the randomly chosen background and foreground colours are different from each other. \$\endgroup\$ Commented Aug 12, 2014 at 20:57

3 Answers 3

5
\$\begingroup\$

The repetition of getting a random font, color, background class cries to be extracted to a utility function:

function pickRandom(arr) { 
 return arr[Math.floor(Math.random() * arr.length)];
}
$("#try-me").click(function() {
 $("#content")
 .hide()
 .removeClass()
 .addClass(pickRandom(font))
 .addClass(pickRandom(color))
 .fadeIn(600);
 $("html")
 .removeClass()
 .addClass(pickRandom(background));
});

I also agree with @MainMa about defining background in terms of color.

Other than that, I think it's nice code!

Ensuring change

If you want to make sure that each font/color/background are different every time the user clicks on the button, then perhaps you can create another helper:

function pickRandomExcept(arr, previous) { 
 while (true) {
 var pick = arr[Math.floor(Math.random() * arr.length)];
 if (pick != previous) {
 return pick;
 }
 }
}

However, in the caller you will need to keep track of the previous picks of each. For example:

var picked_color;
$("#try-me").click(function() {
 picked_color = pickRandomExcept(color, picked_color);
 $("#content")
 .hide()
 .removeClass()
 .addClass(pickRandom(font))
 .addClass(picked_color)
 .fadeIn(600);
answered Aug 12, 2014 at 16:30
\$\endgroup\$
0
4
\$\begingroup\$

One possible improvement consists of removing code duplication between those two arrays:

var color = ["blue", "purple", "yellow", "red", "orange", "green"];
var background = ["bg-blue", "bg-purple", "bg-yellow", "bg-red", "bg-orange", "bg-green"];

Instead, you can build the second array from the first one:

var color = ["blue", "purple", "yellow", "red", "orange", "green"];
var background = color.map(function (c) { return "bg-" + c; })

This has two benefits:

  • If colors change, you have to do the change only once.

  • If the source of colors change (for example you start loading colors from a database or a configuration file), you have to change only the first line.

On the other hand, the drawbacks are:

  • That the code may be more difficult to understand by the beginners.

  • That in your particular case, the duplication is not an important issue: there are only six colors and arrays are easily modifiable by hand.

answered Aug 12, 2014 at 14:40
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice. You could also just prepend the "bg-" when adding the class, i.e. addClass('bg-' + ...), instead of mapping the array upfront. The benefit would be IE 6/7/8 support, since they don't have map \$\endgroup\$ Commented Aug 12, 2014 at 16:50
1
\$\begingroup\$

Well code look good, any changes will be just a over thinking. one thing I want to make here is to specify variable for that calculation.this will make a bit readable ( not a very big point though)

// Switch font randomly
var font = ["lobster", "shadows", "oswald", "josefin", "gloria", "pacifico"];
var color = ["blue", "purple", "yellow", "red", "orange", "green"];
var background = ["bg-blue", "bg-purple", "bg-yellow", "bg-red", "bg-orange", "bg-green"];
$("#try-me").click(function() {
var selectedFontClass=font[Math.floor(Math.random()*font.length)];
var selectedColorClass=color[Math.floor(Math.random()*color.length)];
var selectedBackgroundClass=background[Math.floor(Math.random()*background.length)];
$("#content")
 .hide()
 .removeClass()
 .addClass(selectedFontClass) // Font
 .addClass(selectedColorClass) // Color
 .fadeIn(600);
$("html")
 .removeClass()
 .addClass(selectedBackgroundClass); // Background
});
answered Aug 12, 2014 at 13:22
\$\endgroup\$
1
  • 2
    \$\begingroup\$ On a personal note, I find the original version easier to read vs this version with variables (original looks cleaner). \$\endgroup\$ Commented Aug 12, 2014 at 14:30

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.