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
});
-
1\$\begingroup\$ It's pretty clear and elegant as it is. \$\endgroup\$Carlos– Carlos2014年08月12日 13:14:54 +00:00Commented Aug 12, 2014 at 13:14
-
\$\begingroup\$ I agree with Carlos, looks clear and elegant as it is. \$\endgroup\$jsanc623– jsanc6232014年08月12日 14:31:04 +00:00Commented 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\$200_success– 200_success2014年08月12日 20:57:29 +00:00Commented Aug 12, 2014 at 20:57
3 Answers 3
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);
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.
-
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 havemap
\$\endgroup\$Flambino– Flambino2014年08月12日 16:50:19 +00:00Commented Aug 12, 2014 at 16:50
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
});
-
2\$\begingroup\$ On a personal note, I find the original version easier to read vs this version with variables (original looks cleaner). \$\endgroup\$jsanc623– jsanc6232014年08月12日 14:30:11 +00:00Commented Aug 12, 2014 at 14:30