tutorials.21-lessons.com

Week 4

It is week four, and we're ready to exercise our skills more and more. This week, we're building a chatbot with HTML, CSS, and jQuery. How cool is that?! Let's create a new Glitch Project using the glitch-hello-website template.

Open index.html and replace its contents with this scaffold:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="icon" href="https://glitch.com/favicon.ico" />
  <title>Hello World!</title>
  <link rel="stylesheet" href="/style.css" />

  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script src="/script.js" defer></script>
</head>

<body>
  <div class="chatbot">
    <ul class="responses">
    </ul>
    <form>
      <input type="text" placeholder="Type your question here" class="query" />
      <input type="submit" value="&gt;" class="submit-query" />
    </form>
  </div>
</body>

</html>

This HTML file contains a few HTML elements we'll be using from JavaScript this week.

Also, open styles.css and replace its contents with:

.chatbot {
  display: flex;
  flex-direction: column;
}

.chatbot .responses {
  list-style-type: none;
  height: 500px;
  border: 1px solid grey;
  border-radius: 2px;
  display: flex;
  flex-direction: column;
  overflow-y: scroll;
}

.chatbot form {
  display: flex;
}

.chatbot form input[type="text"] {
  flex-grow: 1.5;
  margin-right: 5px;
}

.chatbot form input[type="submit"] {
  flex-grow: 0.2;
}

.chatbot .responses li {
  margin: 5px;
  padding: 15px;
  color: white;
  border-radius: 4px;
  display: inline-block;
}

.bot {
  align-self: flex-start;
  background: #06BCC1;
}

.user {
  align-self: flex-end;
  background: #6BBAEC;
}

These styles ensure a basic layout and bubbles for our text.

This HTML and CSS skeleton will render a chatbox, a text field, and submit button. It also already has styles pre-configured for message bubbles.

Let's start building the code. Open script.js and delete everything that's in the file.

Setup

In script.js, let's add our jQuery boilerplate to run code once the website has loaded:

$(document).ready(function() {
  //Our code will live here
});

You'll see that certain HTML elements have a class value attached in the HTML file.

CSS classes and how they help us

We already learned that we can reference HTML elements by their tag name in JavaScript and CSS:

  • JavaScript: $('h1').hide()
  • CSS: h1{ color: green; }

That's helpful if we want to implement behavior that affects all tags. But what if we only want to work on a subset, on a particular h1 for instance?

That's where we can leverage classes. First of all, a class is a made-up name we attach to an HTML element, for instance:

<ul class="menu">
  <li><a href="/login">Login</a></li>
  <li><a href="/About">About</a></li>
</ul>

The HTML element still works the same. But now, we're able to reference this element by its class name in CSS and JavaScript. For instance, we can implement a custom style like this:

/*styles.css*/

.menu {
  list-style-type: none;
}

This style disables the bullet points on an unordered list. Or we could use the class name in our JavaScript Code to hide the menu:

$('.menu').hide();

We can apply the class name to several tags on our website. If we had another menu somewhere on our website that should behave the same way, we could add the same class name to those HTML elements.

Greetings, visitor!

Wouldn't it be nice to have our chatbot greet us whenever we visit the site?

chatbot hello

Let's write some code for it.

Open script.js and within $(document).ready, we want to add these lines:

$(document).ready(function() {
  //add the following three lines
  var listElement = $('<li>Hi, how are you?</li>'); // (1)
  listElement.attr({
    'class': 'bot'
  }); // (2)
  $('.responses').append(listElement); // (3)
});

Let's break down what happens here:

(1): We create a new list element. When you look at the HTML code, you'll see that there are a few different tags within <body>. We have an unordered list (<ul>) and a <form>. We'll talk more about the form later. For now, let's concentrate on the list. That's where we'll render our conversation - questions the bot asks and the user's replies. So, in step 1, we're creating a new list element containing a standard greeting for our users. We've seen the $() syntax before to create new elements. What's new here is that we build a new element and assign it to a variable. We do that so we can hold on to it while customizing.

(2): Next, we want to make sure our greeting looks a certain way. Specifically, we'd like to have it look like a chat bubble. The CSS file has a few styles defined in the class .bot. We're using jQuery to add a class to our new element using the (.attr)[https://api.jquery.com/attr/] functionality.

(3): Last but not least, we're appending our new list element to the unordered list defined in the HTML.

Variables

A variable is one of the core concepts of programming. Think of it as a drawer in a dresser. The dresser represents the total amount of memory the computer can access. Whenever your program needs to store something, it creates a variable and assigns the value to it.

In the case of your dresser, you'd put socks in one drawer and also add a label to it, so you remember what's in there. The same applies to variables. They have a name and a value. The value also has a type, for instance, String, Boolean, or Number. Whatever you put in your drawer also has a type: Socks, Shirts, Pants. JavaScript is a dynamically typed language, meaning you don't need to specify a type whenever you declare a variable (declare describes the process of creating a new variable with a name and assigning a value to it.).

Data Types

Variable Explanation 1

Variable Explanation 2

Variable Explanation 3

Reorganzing our code - Refactoring

Wouldn't it be nice for us to be able to generate several bot greetings? We could copy and paste our existing code within $(document).ready to achieve that. But, whenever we're setting out to copy and paste code, we also have the opportunity to make a mistake; read: introducing a bug. Therefore, let's explore how the language supports us to execute code repeatedly without copy-pasting anything. We can take our existing code, adapt it and make it more flexible.

That's where the term refactoring comes up. Refactoring describes the process of restructuring the code without changing its features or behavior. The code might look different after refactoring to make it more usable from the developer's point of view. The end-user won't notice anything; all user-facing features stay the same.

Functions

We already encountered the function keyword a few times. A function serves several purposes within JavaScript. So far, we've used it to group lines of code for window.onload or $(document).ready:

window.onload = function() {
  console.log("Hi there");
};

These are "anonymous functions" because they don't have a name. In the example, a function mainly serves the purpose of grouping lines of code into a unit that should be executed when window.onload gets fired.

We want to use a "named function" to group our code and run it by invoking the function by name.

A named function looks like this:

function botSays(text) {

}

Notice the name between function and the parentheses. The word botSays is arbitrary; the only rule is: it cannot start with a number and cannot include whitespace. You'll notice another identifier between the parentheses: text. text is an argument we need to provide whenever we call the function. Calling a function with a parameter is the equivalent of asking a personal assistant like Siri or Alexa to call somebody. The assistant invokes the call function, and the argument is the person we want to reach.

Refactoring our code

Currently, our code it looks like this:

$(document).ready(function() {
  var listElement = $('<li>Hi, how are you?</li>');
  listElement.attr({
    "class": "bot"
  });
  $('.responses').append(listElement);
});

We want to refactor this code to print several text bubbles without having to duplicate any of the functionality.

Let's start by creating a new function above $(document).ready():

//add these two lines
function botSays() {}

$(document).ready(function() {
  //...
});

In the next step, let's move the three lines of code that generate the chat bubble into our new function, so your code looks like this:

function botSays() {
  //Our code lives up here now.
  var listElement = $('<li>Hi, how are you?</li>');
  listElement.attr({
    "class": "bot"
  });
  $('.responses').append(listElement);
}

$(document).ready(function() {
  //We call the function down here
  botSays();
});

We moved our code into a function and called the function within $(document).ready. If you run your code now, you'll see the functionality stays the same.

As a last step, we'd like to show several bubbles with different text. For that, let's change our code:

function botSays(text) { //change this line
  //Our code lives up here now.
  var listElement = $('<li>' + text + '</li>'); //change this line
  //...

We introduce a parameter to our function: text. Now, whenever we call the function, we need to supply the parameter. Before, we created a list element with a static text. Instead of the static text ("Hi, how are you"), we use our parameter.

But also, what are the plus signs doing there?

When working with numbers, a plus adds up two numbers. It works the same way with strings. Adding two strings together results in one concatenated string:

var result = "Hello " + "Group";
//-> "Hello Group"

Now we can create several text bubbles with any desired text:

function botSays(text) {
  var listElement = $('<li>' + text + '</li>');
  listElement.attr({
    "class": "bot"
  });
  $('.responses').append(listElement);
}

$(document).ready(function() {
  //change these two lines
  botSays('Hi there, how are you?');
  botSays('How can I help you today?');
});