JavaScript Tutorial: Chat

Learn our JavaScript SDK by getting your hands dirty.

Introduction

In this tutorial we will use the public channels feature of the Appstax realtime service to create a minimal chat application. The finished app is available at chat.appstax.io, and the complete code can be viewed in our github repository.

Chat

Install the command line tool

  • Quick install on Mac OSX: Use this command on the terminal:
    curl -s https://appstax.com/download/cli/install_osx.sh | sudo /bin/bash
  • Quick install on Linux: curl -s https://appstax.com/download/cli/install_linux.sh | sudo /bin/bash
  • Manual installation: Download the latest release and copy the appropriate binary to somewhere on your system PATH.

On windows, place appstax.exe in c:\Windows\System32 or any custom PATH you have configured in your environment variables.

Sign up for an appstax account

Go to appstax.com to create your account if you don't already have one.

Create an app with DataStorage and Hosting

Go to the Admin UI and create a new app called "Chat". For this tutorial you only need to enable the Realtime component.

Set up the project on your computer

Open terminal and run these commands to create a new directory called "photbooth" to work in

mkdir chat
cd

Then set up an app in this directory by running

appstax init

Follow the instructions on the screen to log in to your account, and select the app you created before. Select the "JavaScript: Basic project" template and choose a suitable domain name to deploy your app on later. If you type a domain name that is already in use you will be prompted to try again.

The file structure on your computer should now look like this:

chat/appstax.conf
chat/public
chat/public/app.css
chat/public/app.js
chat/public/appstax.js
chat/public/index.html

Set up the UI

Open public/index.html in a text editor and replace its contents with the html shown below. The UI consists of a div#chat container, a ul to display messages and a form to type and send new messages. The html also includes the tags needed to load app.css, appstax.js and app.js.

<!DOCTYPE html>
<html>
<head>
  <title>Chat Example</title>
  <link rel="stylesheet" href="app.css"/>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
</head>
<body>
  <div id="chat">
    <div class="scroll">
      <ul></ul>
    </div>
    <form>
      <input type="text" placeholder="Type a message..."/>
      <button type="submit">SEND</button>
    </form>
  </div>
  <script src="appstax.js"></script>
  <script src="app.js"></script>
</body>

Now open public/app.css and paste in this code to set up the look and feel of the app.

body {
  background-image: radial-gradient(circle, rgba(255,255,255,0.00) 50%, rgba(0,0,0,0.12) 100%);
  margin: 0;
}

#chat {
  margin: 80px auto;
  width: 300px;
  height: 500px;
  display: flex;
  display: -webkit-flex;
  flex-direction: column;
  -webkit-flex-direction: column;
  background: #FAFAFA;
  box-shadow: 0px 6px 51px 13px rgba(0, 0, 0, 0.08);
  border: 10px solid white;
  border-radius: 5px;
  padding: 5px;
}

#chat * {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  background: #FAFAFA;
  font-family: HelveticaNeue-Thin, Helvetica, Arial, Sans-Serif;
  font-size: 14px;
}

#chat .scroll {
  flex-grow: 1;
  -webkit-flex-grow: 1;
  overflow: scroll;
}

#chat ul {
  display: flex;
  display: -webkit-flex;
  flex-direction: column;
  -webkit-flex-direction: column;
  justify-content: flex-end;
  -webkit-justify-content: flex-end;
  list-style: none;
}

#chat li {
  display: block;
  border: none;
  margin-bottom: 5px;
  padding: 10px 60px 10px 10px;
  min-height: 40px;
  background: white;
  position: relative;
}

#chat li .date {
  position: absolute;
  top: 10px;
  right: 10px;
  background: transparent;
  color: #CCC;
}

#chat form {
  margin-top: 5px;
  flex-shrink: 0;
  -webkit-flex-shrink: 0;
}

#chat form input[type=text] {
  width: 100%;
  padding: 10px;
  border: none;
  resize: none;
  background: white;
  outline: none;
}

#chat form button {
  display: block;
  padding: 10px;
  margin-top: 5px;
  width: 100%;
  border: none;
  outline: none;
  background: #66CCEE;
  color: white;
  border-radius: 3px;
}

#chat form button:active {
  background: #3399AA;
}

@media (max-width: 480px) {
  #chat {
    width: 80vw;
    height: 180px;
    margin: 10px auto;
  }
}

Publish and test

Now we will deploy the app to Appstax Hosting to check that everyting is working so far. Run these two commands:

appstax deploy public
appstax open

The first command packages and uploads the contents of the public directory to the Appstax backend. The second command opens your browser at the address where your files are deployed. So if you selected "mychat" as your hosting subdomain you should now be looking at your face on http://mychat.appstax.io/

After each of the next steps you can run appstax deploy public again and reload the browser page to see the changes you've made.

Sending and receiving messages

To set up sending and receiving, paste the following script to the end of public/app.js, then we will take a closer look at the most important parts:

window.addEventListener("load", function() {
  initForm();
  initChannel();
});

function initForm() {
  var form = document.querySelector("#chat form");
  var input = form.querySelector("input[type=text]");
  input.focus();
  form.addEventListener("submit", function(event) {
    event.preventDefault();
    if(input.value != "") {
      var message = {
        text: input.value,
        time: Date.now()
      }
      addMessageToHtml(message);
      sendMessage(message);
      input.value = "";
    }
  });
}

function initChannel() {
  var ch = appstax.channel("public/chat");
  ch.on("message", function(event) {
    addMessageToHtml(event.message);
  });
}

function addMessageToHtml(message) {
  var li = document.createElement("li");
  li.textContent = message.text;
  var date = document.createElement("span");
  date.className = "date";
  date.textContent = formatTime(message.time);
  li.appendChild(date);
  var ul = document.querySelector("#chat ul");
  ul.appendChild(li);
  var scroll = document.querySelector("#chat .scroll");
  scroll.scrollTop = scroll.scrollHeight - scroll.clientHeight;
}

function sendMessage(message) {
  var ch = appstax.channel("public/chat");
  ch.send(message);
}

function formatTime(time) {
  var date = new Date(time);
  return pad(date.getHours()) + ":" + pad(date.getMinutes()) + ":" + pad(date.getSeconds());
  function pad(s) {
    return (s+"").length == 1 ? "0"+s : s;
  }
}

Test with two browser windows

Now run appstax deploy again and open the page in two different windows. Typing a message and hitting enter (or the 'send' button) in one window will make the message appear in both windows.

Code walkthrough

In initForm() we set up an event handler that constructs a javascript object from the value of the text field and the current time:

var message = {
  text: input.value,
  time: Date.now()
}

This object is passed on to addMessageToHtml() that adds the text and timestamp to the html message list. We also call sendMessage() which uses a public channel to send the message:

function sendMessage(message) {
  var ch = appstax.channel("public/chat");
  ch.send(message);
}

To receive messages we hook up to the same channel in initChannel() and pass the received message object to addMessageToHtml():

function initChannel() {
  var ch = appstax.channel("public/chat");
  ch.on("message", function(event) {
    addMessageToHtml(event.message);
  });
}

That's it. Happy chatting!

Things to try on your own

This is the end of the tutorial, but here are a few things you can try to develop this app further:

  • Let people select a ┬źnick┬╗ and display this along with the chat message
  • Add multiple chat rooms using more than one public channel