Chat

For this assignment, you're going to build a real-time chat client. Just like Slack! It's a powerful program to be able to build. Someone types something in on their computer and, BAM, it shows up on your computer. Pretty cool. Let's talk through how it works at a high level:

  1. First, consider what the interface. You'll need a form, input, and submit button to accept user input.
  2. Maybe not as obviously you'll also need a list or some sort of parent to house all the messages. This could be a <div> or a <li>. Remember, the messages you render on screen will come from an API (Firebase) so it's impossible for you to write them by hand with HTML.
  3. Reading: In order to display messages, we're going to write a event handler that listens to events from Firebase, specifically the child_added event. The deal is that Firebase will fire that event for every "child" (aka message) in the database. When that event fires, you should render create the HTML for a new message and put it on screen.
  4. Writing: When your form is submitted (yep, event handler), you want to save the details to Firebase. This is going to be done by calling push() and passing in an object that represents a message. push() is a special method that Firebase gives you for saving/writing data to the database.

OK, that makes sense, but I need more help. Let's dig deeper.

Dealing with Firebase

Firebase has an API that we're going to talk to. But we're not going to talk to it directly, we're going to use their JS library, which makes it even easier.

// Include Firebase's JS library on your page (at the top)
<script src="https://cdn.firebase.com/js/client/2.2.1/firebase.js"><script>

Once that library is loaded, you can connect to the database:

// Connect to the Firebase DB
var firebase = new Firebase("https://blinding-inferno-7422.firebaseio.com");

Now you have a variable called firebase with which you can start to call Firebase specific methods. "blinding-inferno-7422" is an arbitrary database name that Firebase made up when creating the database for this assignment.

Creating a chat message

  1. Add a form to the page
  2. Listen to the form submit event (go back to the todo list for a refresher)
  3. When the form is submitted:
    1. Prevent the default form submit behavior (event.preventDefault()), just like you've been doing with any event handler.
    2. Save the message to Firebase. Call the push() method and pass in a "message" object.
    3. Reset the form (form.reset()). This clears the existing text from the input.
    4. Optionally, focus the text box (so you can keep continue chatting without having to click in the input again to focus it).

A message object isn't anything special, it's just a plain set of key/value pairs. In this case, we want our "message" to look something like this:

var message = {
  username: "avand",
  messageBody: "Hi there, what's the word?",
  createdAt: 1234567
}

Feel free to leave off createdAt for now, if you don't want to deal with dates.

The code above is just a example. The values you actually want to submit have to come from the form and from a prompt. So you'll have to ask for the input's value and prompt the user for a username. Once you have access to those variables, you can pass them along to the "message" object. That might look like this:

var message = {
  username: prompt("What is your user name?"),
  messageBody: document.querySelector("#message").value,
  createdAt: (new Date()).getTime()
}

Display chat messages

  1. Listen to the Firebase "child_added" event
  2. When a child is added, call an event handler
  3. Create the HTML of the message in that event handler
  4. Use the messageBody from the Firebase data to set your message's textContent.
  5. Append your message element to the page

Here's how you listen to the child_added event:

// "on" is just like "addEventListener", it accepts an event type and function as arguments
firebase.on("child_added", createMessageFromFirebase);

// This function will get called for every chat message in the database
function createMessageFromFirebase(snapshot) {
  // The snapshot gives you access to the message data
  // messageData holds the username and body of the each message in the database
  var messageData = snapshot.val();

  // Now you can create a new element and set its textContent from the data
  var messageEl = document.createElement("div");
  messageEl.classList.add("message");
  messageEl.textContent = messageData.messageBody;

  // Not pictured: creating the element you need to house the username
  // (and maybe date if you're feeling adventurous)
}

Asking for a username (only once)

The first time you load this program it should ask you for a username when the first message is submitted. But from then on, it should use the stored value (even if the page reloads). Use localStorage to make this happen.

// When the page loads, create a username var and load it from localStorage
var username = localStorage.getItem("username");

// The first time through, this var will be null because localStorage is empty
if (username == null) {
  // Load the variables value from the results of prompt
  username = prompt("what is your username?");

  // Save it for future use in localStorage
  localStorage.setItem("username", username);
}

What about dates?

Getting dates working is totally optional but dates are just another object you need to be familiar with to get them to work. Here's how you make a new date:

var now = new Date()

That will create a new date object at the current time (and time zone).

Firebase doesn't actually support dates as a data type in the database so you need to save it as different type. Fortunately, dates can be represented as numbers:

var now = new Date();
now.getTime() // => 123456789

That number is what you want to send to Firebase as the createdAt field of the message. So what about displaying the date?

To display dates, you need to turn that number back into a date. Fortunately, that's easy. Just pass the number right into the date constructor. Then, pass that date object to a special strftime() function that will allow you to format the date nicely for humans.

var createdAt = new Date(message.createdAt);
dateElement.textContent = strftime('%a %l:%M %P', createdAt)

The above code will NOT work without the strftime library loaded on the page. The string '%a %l:%M %P' is a special string that you can explore using strfti.me. Here's a URL you can use to load that library:

<script src="http://f.cl.ly/items/2K2Z2g0L3v1q1I413j1O/strftime%20githubcomsamsonjsstrf.txt"></script>