Animations, Transitions and Keeping CSS Kosher

Wrapping up Code School's excellent (and free!) Try jQuery course, and concluded with animations for making an element on the page move up when you click on it. 

There are two ways they show you how to do this. One is by using jQuery's animate() method in your app code (let's call it your app.js file):

$(this).animate({'top': '-10px'}, 'fast');

And the other is to separate out all the styling and store it in your app.css file, and refer to it in your app.js file.  This is what I call "keeping CSS kosher."

// app.js
$('div').on('click', '.someElement', function() {
  $(this).toggleClass('highlight');
});

// app.css 
.someElement {
  transition: top 0.2s; // assumes browser supports CSS transitions
}
.highlight {
  top: -10px;
}

Keeping CSS kosher requires a lot more code, and also assumes browser compatibility. According to CanIUse, about 7 percent of browser usage globally does not support CSS transitions, and half of that comes from Opera Mini, which Jacques (hi, Jacques!) says it's OK to ignore. So that leaves us with 3 percent global usage, or 5.6 percent U.S. (IE 8 and 9 users) unsupported.

So why keep CSS kosher if: 1) It requires more code, and; 2) It leaves out a small but actual percentage of users on unsupported browsers? 

First, it makes it easier to maintain your code if you keep all styling separate. This I know to be true from experience... painful experience.

Second, Jacques says it is way more performant to keep CSS kosher because then your computer will offload transitions to the GPU, which is built to handle tasks like that. 

So, when it comes down to it, your decision tree would be:

  • Do I have to support IE 8 and/or IE 9 users?
    • Yes: Use jQuery methods in your app.js file. Maybe eat a ham sandwich, and wash it down with milk while you're at it. 
    • No: Keep CSS kosher. Create classes in your app.css file, and refer to them in your app.js file.

Google I/O, Android Nanodegree, and Not Doing Homework on Time

Oh my gosh. You guys. I know. I have been really really bad about blogging of late, but I have a good excuse! Which is, um, just lots of work! I have been a busy little bee.

Google I/O 

We launched the Android Developer Nanodegree at Google I/O on Thursday! Or, more specifically, Sundar Pichai announced it at the Keynote, and I launched it from my kitchen table, in my pajamas and rocking a scrunchie (according to the lady who cuts my hair, I have a lot of breakage, so I've taken to wearing scrunchies to bed).

Photo: Techcrunch

Photo: Techcrunch

This was my second I/O, and it was definitely more chaotic than last year. First of all, Udacity and Google had a Developer Training booth this year, where we gave out these phone battery charger thingies in exchange for downloading the Udacity app and signing up for one of our free Google courses. Holy crap. People really wanted those phone charger thingies. They went like hot cakes, if those hot cakes also charged your phone. On Day 2, we ran out and gave away Udacity sunglasses instead. These were markedly less desirable than phone charger thingies. Here is an actual conversation I had with multiple people about the sunglasses:

  • Patron: What are those?
  • Me: Sunglasses. 
  • Patron: OK. But are they 3D? VR? 
  • Me: Um, no, notsomuch. 
  • Patron: (visibly confused) What do they do?
  • Me: Oh! Well! They block 100 percent of UV rays from your eyeball area. Also, there's this nifty Udacity logo on the side... (voice trails off as patron wanders away, distracted by a cardboard box that transports them to outer space) 

I did, at one point, attempt to model the sunglasses. This resulted in one person handing them back to me. Whatever. I am an excellent Booth Human, no matter what people say. 

Also adding to the chaos, the prevailing interior theme of I/O this year seemed to be "low to the ground" because the entire venue was full of bean bag/pouf cushion seats. I think this was supposed to give everything a relaxed, chill vibe. Anyway, it really reminded me of this:

Lounging on dog beds = the new hotness

Lounging on dog beds = the new hotness

At one point, I legit tripped over Sebastian, Udacity's CEO, while en route to get sour apple gummy rings (they were running low, and I panicked). Sebastian, to his credit, does not care in the slightest about getting tripped over, and we went through the slides for his I/O session on democratizing education, which ended up going very well. 

Android Nanodegree 

So this is what I've spent the last 6 months working on. Our team made a whole slate of world-class educational courses with Google, and all these courses are now available to anyone with an internet connection, for free. The Nanodegree is the credential, and that costs money, but the content, itself, is free (and always will be). Weirdly, there are a lot of MOOC haters out there, and I don't really understand what MOOCs ever did to these people besides have a seriously unfortunate acronym, but even the worst hater can't be opposed to bringing free programming courses online, right? 

Trailer video for the Android Developer Nanodegree (Production Credit: Calvin Hu) 

Not Doing Homework on Time

I cleared the soft deadline for Hack Reactor's Section 1 homework, but did not make Section 2 (it's tonight). The hard deadline is at the end of the week, and I'm feeling good about making that one. It's unnerving how quickly time is flying by. My cohort starts in 4 weeks! 

What I'm working on this week: Learning jQuery, implementing a front end, and re-implementing a few advanced Underscore functions. 

Popping and Pushing (more memory tricks)

Definition

The push() and pop() methods add elements to and remove elements from the back of an array.

var arr = [1, 2, 3];
arr.push(4);
console.log(arr); // [ 1, 2, 3, 4 ]
var poppedValue = arr.pop();
console.log(poppedValue); // 4
console.log(arr); // [ 1, 2, 3 ]

Memory Tricks

  • To associate these methods with each other, remember that push-pops are delicious. (I think of them as ice cream treats*, but in my research for this blog post, I discovered that they're actually those weird/gross candy sucker things. Whatever. To me, push-pops = frozen novelties === DELICIOUS)
  • Both of these methods do something to the back of an array, so I like to think of push and pop as a kind of dance method involving your butt. (Like, "Salt-Salt-Salt-N-Pepa's here! ... Want you to push it back!" (and then they do something with their butts) You know that song, right?** #Imightnotbeyoung)
  • I have used push so often that I know it changes the length of an array, but sometimes forget that pop also changes the array -- keeping them associated together will help me remember this.

Keeping these methods straight is pretty intuitive for me, you push something on, and you pop something off. So I don't need a memory trick for that part at least.

* As it turns out, the ice cream treats I'm thinking of are actually called Push-Ups, which sounds like a horribly unpleasant activity to do at all, let alone while eating ice cream.

** Did you know Salt-N-Pepa's "Push It" came out in 1986?!! Also, did you know that video is the best BEST not-actually-a-music-video music video in the history of EVER? I love both Salt and Pepa. I even love the awkwardly capitalized 'N' in between them. Man. If I could, I'd just stop coding right now and watch old Salt-N-Pepa videos ALL DAY.

Arrays! And memory tricks for keeping shift and unshift straight

I just spent about an hour studying arrays. I thought I had a good handle on them, and I'm sure at one point I did, but there was PLENTY of material that I needed to re-study as a refresher. Studying the basics as part of my Hack Reactor precoursework has been very humbling, and I'm really happy that they make us do this!

One thing that I often get confused about is shift() and unshift(). Both of these methods do different things to an array and return non-obvious elements. How to keep them straight? I'll get into that in a moment.

Definitions

The shift() method removes the first element of an array and returns it. It changes the length of the array. If the array has a length of 0, then array.shift() returns undefined .

The unshift() method adds one or more elements to the beginning of an array, and returns the new length of the array. Like shift , it changes the length of the array.

var arr = [1, 2, 3];
console.log(arr.shift()); // 1 
console.log(arr); // [ 2, 3 ]
console.log(arr.unshift(0)); // 3 <- new length of arr
console.log(arr); // [ 0, 2, 3 ]

Memory tricks

Warning: These are silly! But they work for me.

  • Lots of F's: shiFt and unshiFt = the Front of an array.
  • Think of shift like a worker getting off their shift, using a first in [index 0], first out approach. So whoever is at the start of the line [index 0] gets off their shift, and is returned to you. The array actually changes as a result: You have one fewer worker, and all remaining workers are moved up towards the front of the line by one position.
  • Think of the Unshift Family as an annoying family obsessed with how many people they have (like those people who are really into geneology, and keeping ancestry.com in business), so they're going to return the size of their family.
  • Unshift is a fatter word than shift, so of course you're going to end up with a "fatter" array.

I love mnemonic devices (basically attaching a "sticky" mental association to new words so you remember their meanings better - I'm pretty sure that's NOT the scientific definition, btw). I've picked up multiple languages -- from Arabic to Albanian -- using mnemonic devices. The key is not to be embarrassed by the weird turns and graspings that your mind will take in order to attach meaning to a new word or concept. You only need the device while you're learning.

At some point, your reliance on the device falls away and you'll just know that shift() returns the first element of an array, or that "Faleminderit" means "thanks" in Albanian, and you'll evven forget the mnemonic you used to get you there! Brains are awesome like that.

Using Sublime Text for note-taking

We got our pre-course homework from Hack Reactor yesterday! Very exciting. Lots to learn and do. I'm not allowed to share details of the assignments, but can talk generally about my plan to get all of it done.

First, I'm reading up on the documentation they've provided and taking notes. I'm a copious note-taker, and find that it really helps me retain and organize information. I'd like to use Sublime for this, but it's not immediately obvious how to use it for notes in Markdown. 

Enter this blog post, which is tremendously helpful. Less than 15 minutes later, I have Sublime hooked up with Markdown editing and preview, and I'm ready to get started! For my first chunk of work, I have ~300 slides to get through. My goal is to get through 50/day. For me that means I 100 percent understand what's on the slide, and have taken good notes documenting key points, and my thought process for any sample exercises.  

Complete and utter mayhem

That's how I would describe my week.

First of all, I spent last weekend shoveling -- I kid you not -- over 1,000 lbs of dirt from my driveway, and wheelbarrowing it out to the garden. This was very tiring, as you can imagine, especially for someone who dislikes exercise as much as I do. My body was confused by all the exertion, and I was sore all week. 

Second, someone broke into my car and smashed a window. Nothing was stolen because there is nothing in my car worth stealing, unless you're really into pet hair and first aid kits. Anyway, the whole thing was a pain, but I'm grateful it wasn't worse. 

Third, endless work! Endless work! ENDLESS WORK!

On the bright side, I did build a website and I learned about Bootstrap. On the not-so-bright side, my website is a HOT MESS. Oh well. You have to start somewhere, after all. 

Also this week, I refreshed my python skills and coded up a few tests for a work assignment. It was fun, honestly. Python is lovely.

I am so happy it's Friday! Sweet Jesus! 

Hack Reactor homework comes on Monday. I guess I'm as ready as I'll ever be. 

Goals for this week

Last week, my goals were to finish this Treehouse course and to wrap up my Random Number Generator. I managed to do both of these things, but still have some final tasks to complete before I'm satisfied. 

For my RBN, I need to input a conditional so that users can't submit invalid inputs after they submit the same integer values twice. I'll get to this when I'm ready. It shouldn't take too long, but I finally understand why engineers lose so much steam when context switching! 

For the Treehouse course, I finished my project, but need a lot more practice building websites before I feel like I'm making coherent choices. 

This week, my goal is to build a new website. Any website. I'm planning for a light week because this is my last week of study before I get my Hack Reactor homework, and I'd like to knock out some major work projects as well. 

My Random Number Generator now handles weird decimal edge cases

Alright. I think I maybe got this silly thing working as it should. I looked up isNumber and it seems like it basically does an upgraded version of what the conditional in my first while loop does. The thing is, I actually understand what my conditional does (filters out all falsey values except for 0) because I wrote it, and I'm fine with it for now. I might upgrade later once I fully understand isNumber. (As a rule, I don't like writing code that I don't 100 percent understand.)

Anyway, I then tackled the edge cases that have been irking me. Specifically, what if a user inputs something like (3.1, 3.9) as their values? In my previous version, the RNG returns 3 because it applies Math.floor to the max and min, which in this case amounts to (3, 3). But 3.0 is not within the user-defined parameter of (3.1, 3.9). So fooey.

In my newest iteration, I added a new while loop that tests if Math.floor of the min and max are equivalent, and demands a new WHOLE number while this condition is true. I then stored this new value into one of the original nums, and reassigned max and min based on the new value pair.

Finally, I generate a random number, and added new bits of code to the variable that is returned to the user. I rounded-up the min and rounded-down the max to ensure that whatever integer is returned falls within a safe range. OK, this is too many words now. Here is my code.

// collect num1 from user
do {
    // Use parseFloat bc parseInt evaluates non-zero values under 1 as NaN 
    var num1 = parseFloat(prompt("Give me a number!"));
}
while (num1 !== 0 && !num1); // do not accept falsy values except for 0 

// collect num2 from user
do {
    var num2 = parseFloat(prompt("Give me a different number!"));
}
while (num2 !== 0 && !num2); 

// do not accept num2 if it is equal to num1
while (num2 === num1){
    num2 = parseInt(prompt("Give me a DIFFERENT number!")); 
}

// find and store the min and max
var min = Math.min(num1, num2);
var max = Math.max(num1, num2);

// if the Math.floor values are the same, ask for a diff whole number
// accounts for edge cases where user inputs something like (5.4, 5.3) and gets 5 [5.0 falls outside 5.3 - 5.4]
while (Math.floor(min) === Math.floor(max)) {
    // reassign num2 (could also reassign num1), and set new min and max
    num2 = parseInt(prompt("Give me a different WHOLE number!"));
    min = Math.min(num1, num2);
    max = Math.max(num1, num2);
}

// store random whole number in variable to return to user
// round up the min value and round down the max value, so you can return inclusive min/max integers
var randomNum = Math.floor(Math.random() * (Math.floor(max) - Math.ceil(min) + 1)) + Math.ceil(min);

alert("Your random whole number is " + randomNum);
document.write();

Goals for this week

This week I will:

  1. Make time to learn: I have dedicated 6:30am-8:00am on Monday-Thursday for learning. 
  2. Finish the Treehouse How to Make a Website course -- I'm almost halfway done, and have created a spectacularly ugly website! Right now, I'm learning about CSS and styling. Did you know that RGB stands for "Red," "Green," "Blue," and that the 6-character hexadecimal value is just a pairing of the red, blue and green amounts in a color? I did not know this. I also didn't realize that hexadecimal refers to a base-16 numbering system, where the letters A-F stand in for numbers 10-15. That allows you to use a digit of value 0-15 per character, vs just 0-9. All of a sudden, a lot of stuff makes more sense!  
  3. Account for weird decimal edge cases in my Random Number Generator -- Thanks to a tip from fnenu, I will try using the isNumber property.  

I think that's a reasonable amount of stuff for this week. Let's see how I do! 

First ever mailbag post!

Big milestone, you guys. I got TWO questions since setting up my contact page last week. This necessitates (drumroll) a mailbag post! 

Question from a reader on learning callbacks:

Thanks so much for detailing your thoughts and preparation!

How did you further practice callback functions? I have my interview with HR in a week and I feel I still need some practice with them.

Thanks!

My response:

I found that the most useful references for callbacks were the Udacity course that Marcus (cofounder of HR) teaches (he does a good job explaining how the compiler runs through code), and this book.

The best way to practice is to find someone (if you are at university, this should definitely be doable) who can sit down with you while you code, and give you guidance and feedback. At least, that's what worked best for me.

I sat down with a friend and worked through writing the reduce function, using the each function as a callback. That is when I finally understood what I was doing.

For studying the underscore functions (reduce, each, map, etc) in particular, I found that lodash (a superset of underscore) has a more intuitive way of writing the code. You can see how they implemented collection functions like each and reduce by browsing their documentation, or just by opening up the console while on the lodash site and running console.log(_.reduce);

Good luck and don't give up. If this is something you really want to do, you will be able to make it happen.

Best, JK

Question on finding a mentor online:

I was wondering about how would one go about finding a good mentor if they don't live in a city where tech is a big deal. Since I doubt any senior person in the Baton Rouge, LA area is hugely into the web(python especially) I know I would have to find a mentor online, but how?

My response:

It is very hard to find a mentorship from scratch, I agree. Instead, I would look for meetups (meetup.com) in your area, or, if you're able to travel a bit, in the nearest major city.

Then go for a smaller goal of just finding a study buddy who is more of a peer vs. a senior dev.

Ultimately, I think a study buddy is more useful than a mentor when you're starting out in programming (if that is indeed the case for you). You can learn from people you admire online by following their blogs, tweets, LinkedIn articles, and Github activity. But when you're starting out, nothing beats having someone to slog through problems together, and to help keep you accountable.

If you are looking for more structure, Udacity has a Nanodegree program that you might be interested in. It is $$ though ($200/mo). They do provide Coaches and a private community forum for support, so it kind of gives you that mentorship feeling. They also give you code review and feedback on projects, and that can be really helpful when you're learning. [Full disclosure: I work for Udacity, but I do not benefit financially from new sign-ups or anything like that.]

Best, JK


Where has this week gone?!

How is it Thursday already? Here's what I've been up to:

  • Trying to get a dev environment set up on my machine for work. This sucked up many many many hours of time! Eventually I gave up, BUT I did practice a lot of command line in the process. So not a total loss. 
  • Redoing the random number generator to handle edge cases like when a user inputs 5.4, and 6, and the generator returns 5, which was not in their set range. What I want to happen is for the generator to accept 5.4 from the user, and then round it up to 6 when it sets the min and max values. This would set both the min and max values to 6, so the generator would only return 6. For a pairing like (5.4, 7), the generator would return 6 or 7. 
  • Building regular expressions. I've been testing on regexr
  • Putting out various work-related fires! 

Basically, it's been a very hectic week, and I expect the frenetic pace to continue up until Google I/O. I'm not sure if I'm going this year, but it's a big event for us and we're doing lots of cool stuff to prepare for it. 

At this rate, I'm a tiny bit concerned about how I'm going to keep up with Hack Reactor's pre-coursework, which they're releasing to our cohort later this month. If you don't complete it, you get kicked out of the program. So... I'm going to have to find time wherever/however I can.

Getting out of the "Code Sinkhole": A less crazy random number generator

Chatted with fnenu this morning about the state of my poor random number generator. I really built a monster from what was supposed to be a simple exercise. Welcome to programming, I suppose. Anyway, it FINALLY occurred to me that there was no need to calculate the difference between the max and min values, since the min value is subtracted from the max before being multiplied by Math.random().

And then I figured I should just use Math.max() and Math.min() to identify the upper and lower (inclusive) bounds for the set of possible numbers returned to the user. It feels a little weird applying them to a set of 2 numbers, but the code certainly does not suffer from the omission of extraneous if statements that I had in my previous version.

I think what this illustrates is, even "simple" coding problems can quickly take on a life of their own, and before you know it you're passing in conditionals and callbacks left and right. I think of this as falling into the "code sinkhole." If you sense yourself getting stuck down there, it might be a good time to get a snack or take a walk. Because you don't want to be in the code sinkhole for too long.

// TODO: deal with non-number inputs

// collect num1 from user
var num1 = parseInt(prompt("Give me a number!"));

// collect num2 from user
var num2 = parseInt(prompt("Give me a different number!"));

// do not accept num2 if it is equal to num1
while (num2 === num1){
  num2 = parseInt(prompt("Give me a DIFFERENT number!")); 
}

// find and store the min and max
var min = Math.min(num1, num2);
var max = Math.max(num1, num2);

// use Math methods to generate random num 
// store in variable to return to user
// need to start from the min (inclusive), rather than start from 0
var randomNum = Math.floor(Math.random() * (max - min + 1)) + min;

// alert the randomNum to user
alert("Your number is " + randomNum);
document.write();

Code review and changes for my Random Number Generator

If you recall, last week, I made a random number generator as part of the Treehouse JS Basics course. Well, after fnenu did code review, I realized I had some weird stuff going on there!  

The easiest way to explain the mistakes I made is to see the diff.  

This seems like a lot more code, and I'm sure there are ways to slim it down. (Pull requests welcome!) 

Using JavaScript to solve a real life problem!

This is for fnenu, who reminded me that I have yet to post this month!

OK, so I totally missed out on April Fools Day and had no time to create a fun fool-themed post (one of the many untethered ideas I come up with while commuting). So instead I'm going to talk about the first time I used code to solve an actual problem I was having. This was a very powerful moment for me because it took all this learning that was living  ^way up here ^  in my mind, and brought it down to earth.  

I've been trying to reorder checks through my credit union's website for months, but their partner site wouldn't allow me to edit the information (name and address) listed on the check. Even after I called my credit union to change the associated address, the partner site added a number tag to my name that was visible on the check in an uneditable text field. 

Seemingly uneditable, I should say. Because once you know your way around a JavaScript console, you have access to a whole new world of possibilities. 

I opened the console, located the div in question, and manually changed the text to be displayed just how I wanted it. When I proceeded to the checkout screen, the changes I made were reflected on the final product! Victory!!! I felt like a low-rent hacker. Which is to say, I felt indescribably proud. 

I got my checks delivered today, opened them up, and sure enough, they are exactly as I wanted! (Side note: It kind of feels like, since it's a site tied to banking, maybe you shouldn't be able to do this so easily? But whatever. I got my checks to look right, so YAY.)

Thinking back to the last time I struggled to reorder these stupid checks a few months ago, I never would have imagined that I'd be able to overwrite what I saw on that janky web page with just a few short keystrokes. I think that's the most powerful part of programming -- discovering that there are SO MANY possibilities for doing stuff that you hadn't ever considered before, and knowing that there is real, non-magical code behind the page that you can access and manipulate. 

NaN !== NaN (aka JavaScript==='CRAZY')

Working on re-implementing lodash, and discovered this expression in their comparator function:

var valIsReflexive = value === value; 
// um.. WTH is THAT ^^^^^^^^ 

Not understanding why there were two separate "equals" statements (the first as an assignment, and the second as a strict equality operator), I asked my friend Lindsey for help. She explained that the '===' is making a comparison, and the value of the comparison, value === value (true or false), is then stored in the variable, valIsReflexive.

Which then begs the question, when would value === value ever evalute to false?

So back to Stack Overflow I went, and eventally landed here.

And that's where I learned that NaN is, like, totally crazypants. I ran a few tests in my code, to confirm this; results below.

console.log(NaN===NaN);
// false
console.log(3/0===4/0);
// true

And then, I was like, "WAT." (You should totally watch that, btw. Gary Bernhardt === GOLD.) But then fnenu asked, "What if you set those values to variables, does it still evaluate to false?" This is an excellent question, so I ran another test:

var wat = NaN;
var waat = NaN;
console.log(wat===waat);
// false
console.log(wat===wat);
// false   <-- I KNOW, RIGHT?! 

GAH. Mind, bent.

Code conventions for JavaScript

Praise be to Stack Overflow for leading me to this gem by JS guru Douglas Crockford. 

I'm studying the lodash documentation (more on this later) and wondered what the ALLUPPERCASE named variables were supposed to be, so I searched for it and stumbled upon a great resource that I hadn't been expecting, but am so totally ready to consume. Behold, Internet! 

Goals for the week

Last week was kind of meh, with respect to learning. I finally finished the Treehouse command line course over the weekend, which was pretty rewarding. Midway through the course, I stopped using their workspace, and just practiced directly inside the terminal on my machine. Previously, that would have scared the crap out of me (and at one point I inadvertently hit "enter" after a sudo command, but thankfully the terminal stopped me with an "Are you sure?" prompt before it executed), so I definitely have made progress against one of my pre-Hack Reactor goals.

Now to tackle everything else! I tend to do best when I break down my goals in manageable chunks. Here are my learning goals for this week:

  • Complete the Treehouse JavaScript Basics course (I have one lesson left)
  • Make a list of the things I need to learn before resuming the Udacity JavaScript Design Patterns course. I'm super excited to finish this one because it feels very authentic compared to other courses I've taken, AND because Ben Jaffe is a superb teacher and a personal friend of mine. I've completed one lesson, but didn't feel like I really mastered the content, so want to do my homework before restarting. But FIRST, I need to itemize what that homework is. 
  • Touch code everyday. This is important!!! Need to get into a daily habit of coding in JavaScript, even if it's just a line or two in the Chrome console. 

What I'm Learning Today: Olympics quiz with lots of conditional statements

Almost done with the Treehouse JavaScript Basics course. The project for conditional statements involves creating a quiz that keeps track of the user's inputs, and awards a crown based on how many questions they got right. I made my quiz about the Olympics because I love the Olympics.

// Ask at least five questions
// TODO: Deal with invalid user inputs
// Keep track of the number of questions the user answered correctly
var counter = 0;
var crown = '';

var gabbyDouglas = prompt("What gymnast won the gold medal in the women's all-around competition at the 2012 Olympic Games? \na) Aly Raisman \nb) Gabby Douglas \nc) Victoria Komova \n \nWrite your answer (a, b or c) in the box below.").toLowerCase();

if(gabbyDouglas==='b'){
  counter++;
}

var phelpsGold = prompt("How many gold medals did Michael Phelps win at the 2008 Olympic Games? \n \na) Six \nb) Seven \nc) Eight \nd) Nine \n \nWrite your answer (a, b, c or d) in the box below.").toLowerCase();

if(phelpsGold==='c'){
  counter++;
}

var magSeven = prompt("What was the nickname of the U.S. women's gymnastics team that brought home the gold at the Atlanta Games? \n \na) The Fab Five \nb) The Magnificent Seven \nc) The \'A\' Team \nd) The Three Musketeers \n \nWrite your answer (a, b, c or d) in the box below.").toLowerCase();

if(magSeven==='b'){
  counter++;
}

var coachDaly = prompt("Who was the head coach of the 1992 U.S. men's Olympic basketball team, known as \'The Dream Team?\' \n \na) Mike Krzyzewski (Coach K) \nb) Mike D'Antoni \nc) Chuck Daly \nd) Lenny Wilkens \n \nWrite your answer (a, b, c or d) in the box below.").toLowerCase();

if(coachDaly === 'c'){
  counter++;
}

var michaelPhelps = prompt("Which Olympian holds the record for most total medals, for either the Summer or Winter Games? \n \na) Michael Phelps \nb) Larisa Latynina \nc) Carl Lewis \nd) Mark Spitz \n \nWrite your answer (a, b, c or d) in the box below.").toLowerCase();

if(michaelPhelps==='a'){
  counter++;
}

// Rank the player. 
// If the player answered all five correctly, give that player the gold crown: 
// 3-4 is a silver crown; 
// 1-2 correct answers is a bronze crown and 
// 0 correct is no crown at all.
if(counter>4){
  crown = "gold";
} else if(counter>2){
  crown = "silver";
} else if(counter>1){
  crown = "bronze";
} else {
  crown = "\'try again\'";
}

// Provide a final message after the quiz letting the user know the number of questions he or she got right.
alert("You got " + counter + " out of 5 answers correct! \nYou win the " + crown + " crown!");

document.write();

And here is the HTML file: 

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="css/main.css">
  <title>The Ultimate Quiz Challenge</title>
 </head>
<body>
  <div class="container">
  <h1>The Ultimate Quiz Challenge</h1>
   <script src="quiz.js"></script> 
  </div>
</body>
</html>