Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

These are my slides and outline for TartanHack Javascript tech talk

branch: master

Fetching latest commit…

Octocat-spinner-32-eaf2f5

Cannot retrieve the latest commit at this time

Octocat-spinner-32 final
Octocat-spinner-32 README.markdown
Octocat-spinner-32 slides.key
Octocat-spinner-32 slides.pdf
README.markdown

Javascript/jQuery

These are just my slides for a tech talk I gave on 2/4/2012 at Carnegie Mellon University. It is an entry-level Javascript/Introduction to jQuery talk.

Introduction

Let's start by logging something to the console. The console.log('...') method is very helpful in debugging and producing output outside of the webpage. It's similar to System.out.println() in Java or puts in Ruby.

Let's make a basic "Hello World" application. Open up the web inspector by choosing View -> Developer -> Developer Tools. Click on the "Console" tab.

This is an interactive development console, similar to irb in Ruby. We can type directly into it:

console.log("Hello World")

Technically, we should end this with a semicolon, but javascript is generally smart about guessing where you wanted semicolons. Also, there's no specification for using double or single quotes. We could just as easily write:

console.log('Hello World')
var todos = [];
function addTodo(item) {
  todos.push(item);
}

function removeTodo(index) {
  todos.splice(index, 1);
}

[Use this opportunity to discuss variable scope (with var, inside braces, etc)]

[Demonstrate adding and removing from list]

DOM

Let's take our console application and give it a nice interface for the user. Here, we will be interacting with the DOM - Document Object Model. Let's create a simple HTML page. Create a new project directory and create a new empty file in your favorite plain text editor:

<html>
  <head>
    <title>Seth's Todo App</title>
    <link rel="stylesheet" href="./stylesheets/application.css" />
  </head>

  <body>
    <header>
      <h1>My Todos</h1>
      <input type="text" id="new-todo" placeholder="New Todo" />
      <button id="new-todo-button">Add</button>
    </header>

    <div id="todos-list"></div>
  </body>
</html>

Open the page in your browser. This is pretty basic, but it will suffice. Let's add some interactive javascript code that alerts the user "Ouch! That hurts!" when the user clicks the "Add" button:

<script type="text/javascript">
  var newTodoButton = document.getElementById('new-todo-button');

  newTodoButton.onclick = function(e) {
    alert("Ouch! That hurts!");
  }
</script>

Jumping back to the browser and clicking refresh, nothing has changed. However, if we click the button, we get a nice alert.

Ultimately we want to add what the user puts in the textbox to our Todo list. First, let's get the user's input:

<script type="text/javascript">
  var newTodo = document.getElementById('new-todo');
  var newTodoButton = document.getElementById('new-todo-button');

  newTodoButton.onclick = function(e) {
    alert(newTodo);
  }
</script>

When we click the button... Well, that's not very helpful. Javascript doesn't automatically assume you want the value back. Let's fix our code to return the value of the textbox:

    alert(newTodo.value);

Now, when we type text into the textbox and click the button, the alert tells us the content of the textbox. Yay!

However, there's no state to our application. Ideally, we want a way to store these todos somewhere on the page...

In our earlier example, we were storing the todos in a javascript array... let's port that code here:

<script type="text/javascript">
  var todos = [];
  var newTodo = document.getElementById('new-todo');
  var newTodoButton = document.getElementById('new-todo-button');

  newTodoButton.onclick = function(e) {
    //alert(newTodo.value);
    addTodo(newTodo.value);
  }

  function addTodo(item) {
    todos.push(item);
  }

  function removeTodo(index) {
    todos.splice(index, 1);
  }
</script>

But nothing is happening when I click add! If we open up the console, we can see that our items are actually added to the todos array. Why isn't it showing up on our page? We haven't told javascript what to do with the data.

Let's write another method called printTodos that lists all our todos on the page:

  var todosList = document.getElementById('todos-list');

  function listTodos() {
    for(var i = 0; i < todos.length; i++) {
      var div = document.createElement('div');
        div.className = 'item';
      var content = document.createElement('span');
        content.innerHTML = todos[i];

      div.appendChild(content);
      todosList.appendChild(div);
    }
  }

If we try it again... Nothing's happening! That's because we need to call our listTodos() method each time we click the add button:

  listTodos();

If we try this a couple times, we immediately see a bug... There's a bunch of duplicates. We need to clear that div before we append more another todo:

function listTodos() {
  // clear the existing list
  todosList.innerHTML = '';

  for(var i = 0; i < todos.length; i++) {
    var div = document.createElement('div');
      div.className = 'item';
    var content = document.createElement('span');
      content.innerHTML = todos[i];

    div.appendChild(content);
    todosList.appendChild(div);
  }
}

While we're at it, it would be nice if the textbox was cleared when we click the add button. Let's add that functionality:

function addTodo(item) {
  todos.push(item);
  newTodo.val('');
  listTodos();
}

I shouldn't have to click the button if I don't want, I should be able to press the enter key inside the textbox. Let's add that now. We are going to delegate this method to the button.

newTodo.onkeypress = function(e) {
  if(e.keyCode === 13) {
    newTodoButton.click();
  }
}

We use ===, instead of == here, to ensure javascript doesn't match anything we don't want it to.

Cool. Now when we press enter, we effectively click the button.

Let's also add a way to remove a todo from the list. We are going to create a link, attach a click handler, then append it to the DOM:

function listTodos() {
  // clear the existing list
  todosList.innerHTML = '';

  for(var i = 0; i < todos.length; i++) {
    // using string concatenation instead
    var link = document.createElement('a');
      link.className = 'delete-todo-link';
      link.setAttribute('data-remove-index', i);
      link.innerHTML = '&times;';
      link.onclick = function() {
        removeTodo(this.getAttribute('data-remove-index'));
      }

    var div = document.createElement('div');
      div.className = 'item';

    var content = document.createElement('span');
      content.innerHTML = todos[i];

    div.appendChild(link);
    div.appendChild(content);

    todosList.appendChild(div);
  }
}
function removeTodo(index) {
  todos.splice(index, 1);
  listTodos();
} 

That's cool. Now, let's add a magical stylesheet and our application will come to life.

<link rel="stylesheet" href="./stylesheets/application.css" />

Now that we have a functional application using javascript, let's make our life a lot easier by using jQuery.

First, download jQuery from jquery.com. Attach jQuery to our HTML page:

<script type="text/javascript" src="./javascripts/jquery.js"></script>

By default, jQuery uses the dollar sign ($) as it's selector. To select a simple element, we just wrap it in the dollar sign. Furthermore, jQuery mimics CSS selectors like the hash for ids.

var newTodo = $('#new-todo');

This is much shorter and more understandable. Let's replace all our document.getElementById calls with this (do that)...

jQuery also has built-in support for events. These events are the same as "regular" javascript, but they aren't prefixed with the "on" keyword. For example, we can rewrite our click method for newTodoButton like this:

newTodoButton.click(function(e) {
  addTodo(newTodo.val());
});

Notice how the click method actually takes a parameter, but that parameter is a function. Remember that functions are first-class objects in javascript.

Let's do the same for our onkeypress:

newTodo.keypress(function(e) {
  if(e.keyCode === 13) {
    newTodoButton.click();
  }
});

We could rewrite all of our selectors and attribute methods in jQuery, but for sake of time, I want to move on to new things we can do with jQuery, such as animations. With jQuery, we can completely remove our array and just use the DOM as our holder.

I want my post-it notes to fadeIn when the user clicks the add button.

var newTodo = $('#new-todo');
var newTodoButton = $('#new-todo-button');
var todosList = $('#todos-list');

newTodoButton.click(function(e) {
  addTodo();
});

newTodo.keypress(function(e) {
  if(e.keyCode === 13) {
    newTodoButton.click();
  }
});

function addTodo() {
  var link = $('<a />');
    link.addClass('delete-todo-link');
    link.html('&times;');
    link.click(function() {
      var item = $(this); // reference wrapping
      item.parent().fadeOut('fast', function() { // make note of callback functions
        $(this).remove();
      });
    });

  var div = $('<div />');
    div.addClass('item');
    div.addClass('hide');

  var content = $('<span />');
    content.html(newTodo.val());

  div.append(link);
  div.append(content);

  todosList.append(div);

  // reset the value
  newTodo.val('');

  // append it nicely
  div.fadeIn('fast');
}

Externalizing Javascript

Mention this if there's time.

Something went wrong with that request. Please try again.