Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I discovered the FizzBuzz test while looking up something else on stackoverflow, so I decided to try it and see what I would come up with. I'm kind of new to jquery and js, so I'm looking for a critique on my code. What can I do better? Changes? Simplifications?

My priorities on this were -

  1. Maintainability & readability
  2. A page that was responsive to browser resizing & different screen sizes
  3. Presenting it in a nice format without overdoing it. I came up with a simple, 4 column static version in about 45 minutes, but then refactored and styled it quite a bit.

Two additional notes:

  1. I used the defer attribute in my script tag and put it in the head.

    <script src="fizzbuzz.js" charset="utf-8" defer="defer"></script>
    

    Is that acceptable? Is there a better way?

  2. Setting intervals/timeouts still confounds me. How would you create a small interval between each number line printing, such that they print out sequentially and in an animated manner. I think you would need setInterval() or setTimeout(), but I'm not really sure how to use it without breaking everything.

Here's a copy of the code, edited per st88's suggestion. The old calculateColumns() function is commented out, and has been replaced by two functions (createColumns and calculateColumns) that deal with the conditional differently and remove a repeating code error.

var fizzContainer = $("div.number-container");

var divisor1 = 3,
  divisor2 = 5,
  maxFizz = 100,
  word1 = "Fizz",
  word2 = "Buzz",
  windowWidth = window.innerWidth,
  minNumOfColumns = 1,
  maxNumOfColumns = 12,
  widthPerColumn = 150,
  columns,
  linesPerColumn,
  columnSizingParameters = {};

calculateHeading(windowWidth);
calculateColumns();
createColumns();

$(window).resize(function() {
  windowWidth = window.innerWidth;
  calculateHeading(windowWidth);

  $(".number-container").replaceWith("<div class='number-container'></div>");
  createColumns();
});

function calculateHeading(windowSize) {
  if (windowSize <= 500) {
    $("h1").attr("class", "transition xSmallHeading");
  } else if (windowSize <= 700) {
    $("h1").attr("class", "transition smallHeading");
  } else if (windowSize <= 1000) {
    $("h1").attr("class", "transition mediumHeading");
  } else if (windowSize >= 1000) {
    $("h1").attr("class", "transition largeHeading");
  }
}


// function calculateColumns() {
//    for (var i = 1; i <= maxNumOfColumns; i++) {
//       if ((windowWidth >= columnSizingParameters[i]) && (windowWidth <= columnSizingParameters[i + 1])) {
//            columns = i;
//            break;
//       }
//    }
//    linesPerColumn = Math.ceil(maxFizz / columns);
//    createNumbers();
// }

function calculateColumns() {
  var columnIt = minNumOfColumns - 1;
  for (columnIt; columnIt <= maxNumOfColumns; columnIt++) {
    columnSizingParameters[columnIt] = columnIt * widthPerColumn;
  }
}

function createColumns() {
  for (var i = 1; i <= maxNumOfColumns; ++i) {
    if (columnSizingParameters[i] > windowWidth) {
      columns = i - 1;
      break;
    }
  }
  linesPerColumn = Math.ceil(maxFizz / columns);
  createNumbers();
}

function createNumbers() {
  var i = 1;

  for (var c = 1; c <= columns; c++) {
    var col = $('<div></div').appendTo(".number-container");
    col.addClass('column');

    for (var a = 1; a <= linesPerColumn && i <= maxFizz; a++, i++) {
      if ((i % divisor1 === 0) && (i % divisor2 === 0)) {
        createContentLine(word1 + word2, "double-match", col, i, true);
        continue;
      } else if (i % divisor1 === 0) {
        createContentLine(word1, "match-1", col, i, true);
        continue;
      } else if (i % divisor2 === 0) {
        createContentLine(word2, "match-2", col, i, true);
        continue;
      } else {
        createContentLine(i, "num", col, i, false);
        continue;
      }
    }
  }
}

function createContentLine(toPrint, cssClass, col, i, appendNumToWord) {
  var contentLine = $("<p>" + toPrint + "</p>").appendTo(col);
  contentLine.addClass(cssClass);

  if (appendNumToWord) {
    var appendedNumber = $("<span></span").appendTo(contentLine);
    appendedNumber.text(" • " + i).addClass("num");
  }
}
* {
  padding: 0px;
  margin: 0px;
  box-sizing: border-box;
}
.container {
  width: auto;
  height: 100%;
  display: block;
}
h1 {
  display: block;
  background-color: black;
  color: white;
  width: 100%;
  font-family: 'Berkshire Swash', cursive;
}
.transition {
  transition: 500ms;
}
/* Screen width Less than 500px */

.xSmallHeading {
  font-size: 25px;
  line-height: 25px;
  padding: 15px;
}
/* Less than 700px */

.smallHeading {
  font-size: 32px;
  line-height: 32px;
  padding: 20px;
}
/* Less than 1000px */

.mediumHeading {
  font-size: 40px;
  line-height: 40px;
  padding: 30px;
  margin-bottom: 10px;
}
/* Greater than 1000px */

.largeHeading {
  font-size: 50px;
  line-height: 50px;
  padding: 40px;
  margin-bottom: 20px;
}
.number-container {
  display: flex;
  margin-top: 20px;
  margin-bottom: 20px;
  text-align: center;
  line-height: 30px;
  width: 100%;
  height: calc(100% - 150px);
}
.column {
  flex-grow: 1;
  display: inline-block;
  border-right: 1px solid lightblue;
}
.column:last-of-type {
  border-right: none;
}
.num {
  color: #585858;
  font-weight: bold;
  font-style: normal;
  font-family: sans-serif;
  font-size: 12px;
}
.double-match {
  font-weight: 600;
  font-size: 20px;
  color: #3f89d6;
  font-family: 'Crimson Text', serif;
}
.match-1,
.match-2 {
  font-family: 'Josefin Slab', serif;
  font-weight: 700;
  font-size: 18px;
}
.match-1 {
  color: #7ac962;
}
.match-2 {
  color: #ba62d4
}
<html>

<head>
  <meta charset="utf-8">
  <title>FizzBuzz in Javascript</title>

  <link href='https://fonts.googleapis.com/css?family=Berkshire+Swash|Crimson+Text:600|Josefin+Slab:700' rel='stylesheet' type='text/css'>

  <link rel="stylesheet" href="style.css" media="screen" charset="utf-8">

  <script src="https://code.jquery.com/jquery-2.2.3.min.js" integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo=" crossorigin="anonymous"></script>

  <script src="fizzbuzz.js" charset="utf-8" defer="defer"></script>
</head>

<body>
  <div class="container">

    <h1>The fizzbuzz test...in Javascript!</h1>

    <div class="number-container">

    </div>
  </div>
</body>

</html>

I also put it on CodePen, for those so inclined.

share|improve this question
    
Wouldn't it be enough to check ... " if (columnSizingParameters[i] > windowWidth) { columns = --i; } " ? On the first column which is bigger then allowed you stop and take the one before. Because that one was still alright. – st88 May 2 at 6:47
    
Yup your right. I changed it to that, but with a break at the end so I don't always end up with 12 columns. I also separated the calculateColumns() function in to two, calculateColumns(), which defines the columnSizingParameters[], and createColumns(), which does the creation. Looking at it again made me realize that there was no need to redefine columnSizingParameters every time the page is resized. – Alessia May 3 at 20:14

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.