JavaScript Through Facebook Hacks/Hackers Buenos Aires. Aug., 2012

Follow Along
http://j.mp/hhba-js

Schedule

1. JS Crash Course
2. DOM/jQuery
3. Facebook API
4. Your turn

Running JS in the browser

<script>
  // code here
</script>
  
<script src="yourscript.js"></script>
  

The console

console.log("stuff");
  

Intro.

Programming is 3 things

Assignment, Conditional, Iteration

Assignment

var name = "Al";

Conditional

if (name === "Al") {
  console.log("hello, " + name);
}

Iteration

var names = ["Al", "Joe", "Sally"];
for (var i = 0; i < names.length; i++ ) {
  console.log(name + " is here!");
}
  

Let's go!

var
var address = 20;
var street  = "Cooper Sq.";
var city    = "New York";
var state   = "NY";
var zip     = 10003;
    
city + state;
//=> "New York, NY"
      
address + zip;
//=> 10023
          
address + street + zip;
//=> "20Cooper Sq.10003"
        
address + ", " + zip;
//=> "20, 10003"
        
address + " " + street;
//=> ?
        
address + " " + street;
//=> "20 Cooper Sq."
        
var initial = 10;
10 += 10;
//=> 20;
              
var str = "";
str += initial;
//=> ?;
            
var str = "";
str += initial;
//=> "10";
            
= vs. ===
var a = 3;
var b = 3;

a === b
//=> true
var a = 3;
var b = 3;

if (a === b) {
  console.log('they match');
}
var a = 1;
var b = 2;

if (a !== b) {
  console.log("They don't match!");
}
var a = 3;
var b = 3;

if (a === b) {
  console.log('they match');
} else {
  console.log("they don't match");
}
var printAddress = function(address, street, city, state, zip) {
  str = "";
  str += address + " " + street;
  str += "<br>";
  str += city + ", " + state + " " + zip;
  return str;
}
        
printAddress(address, street, city, state, zip);
//=> "20 Cooper Sq.<br>New York, NY 10003"
              
var address = 10;
printAddress(address, street, city, state, zip);
//=> "10 Cooper Sq.<br>New York, NY 10003"
          
person = {};
var person = {};
person.first_name = "Al";
person.last_name  = "Shaw";
var person = {};
person['first_name'] = "Al";
person['last_name']  = "Shaw";
var people = [];
people.push(person);
people[0];
//=> 
{
  first_name : "Al", 
  last_name  : "Shaw"
}
people.length
//=> 1
var students = ["Amy", "Joe", "Sally", "Harry"];
students[0]
//=> "Amy"
students[1]
//=> ?
students[1]
//=> "Joe"
var i;
for (i = 0; i < students.length; i += 1) {
  console.log(students[i] + " is in class today");
}
//=>
Amy is in class today
Joe is in class today
Sally is in class today
Harry is in class today
var even_numbers = [2, 4, 6, 8, 10];
var odd_numbers  = [];
// how can we programmatically 
// fill up this array with odd numbers
var i = 0;
for (i = 0; i < even_numbers.length; i+= 1) {
  odd_numbers.push(even_numbers[i] + 1);
}
console.log(odd_numbers);
//=> [3, 5, 7, 9, 11]
// Who's in class today?
var attendance = {
  "Amy"   : true,
  "Joe"   : true,
  "Sally" : false,
  "Harry" : true
};
var isInClass = function(student) {
  if (attendance[student]) {
    console.log("Here");
  } else {
    console.log("Absent");
  }
};
// Try it
isInClass("Sally");
//=> Absent
isInClass("Joe");
//=> Here

JS vs. The DOM

HTML: Structure
CSS: Presentation
JS: Behavior

<div id="target"></div>
#target { 
  color:black;
}
// the DOM
// scripting the elements on a web page
var target = document.getElementById("target");

the DOM is the page from JavaScript's perspective

$

jQuery makes the DOM easy

jQuerify your browser
so you get jQuery in your console

http://www.learningjquery.com/2006/12/jquerify-bookmarklet
var target = $("#target");

vs. 

document.getElementById("target");

Use CSS Syntax

tag:        $("input");
id:         $("#target");
class:      $(".target");
attributes: $("input[type=submit]");

Add Behavior!

<div id="target"></div>
<div id="result"></div>

$("#target").click(function() {
  $("#result").html("You clicked!");
});

//=> <div id="result">You clicked!</div>
OR

<div id="target"></div>
<div id="result"></div>

var showClickText = function() {
  $("#result").html("You Clicked");
}

$("#target").click(showClickText);

jQuery isn't a JS Replacement

Use jQuery to query the DOM

Manipulation, Traversal, AJAX

There are  slides in this deck.
// That just happened live!
There are <span class="slidect"></span> slides in this deck.

$(".slidect").html($("div").length)
<style>
  .box {
    width:200px;
    height:200px;
  }
  .redbox {
    background:#ff0000;
  }
  .blackbox {
    background:#000;
  }
</style>

<div class="box redbox"></div>


$(".box.redbox").addClass("blackbox");
$(".box.redbox").removeClass("redbox");
<div class="goaway"></div>

$(".goaway").remove();

Add CSS on the fly!

// turn redbox into purplebox
$(".box.redbox").css("background", "purple");
// Bind to elements
$(".target").click()

// an expansion of
$(".target").bind("click");

"Binding" is trapping events the browser emits whenever the user does anything

$(".target").click( /* do something */ );
// Pass a "callback" function
$(".target").click(function() {});
// Pass a "callback" function
$(".target").click(function() {
  console.log("You clicked the target");
});

Callbacks, by convention, are functions that get called after other functions run.

// Example
var doSomething(cb) {
  doTask();
  if (cb) { cb() }; //callback is invoked
}
// Calling the function
doSomething(function() {
  //do something else;
})
// You don't have to invoke the callback function,
// the parent function invokes it.

Operating on many elements with jQuery

// turn all links red
$("a").each(function() {
  $(this).css("color", "red");
})
this

If you understand `this`, you understand JavaScript.

But, to understand `this`, you need to understand prototypes.

This gets kinda advanced.

// set up the room
var Animal = function(kind, sound) {
  this.kind  = kind;
  this.sound = sound;
}
Animal.prototype.speak = function() {
  console.log(this.sound);
}
// instantiate it
var cat = new Animal("cat", "meow")

// make it speak
cat.speak()
//=> meow
// instantiate it
var bear = new Animal("bear", "grrrr")

// make it speak
bear.speak()
//=> grrr
// add a new method on the fly
Animal.prototype.sayMyName = function() {
  console.log(this.kind);
}

cat.sayMyName();
//=> "cat";

Animal is what we call a `class`.

It can create as many animals as you want.

Use `this` to stash attributes in the class.

Why you should care, if you're just using jQuery.

`this` is slippery with callbacks.

// Let's have the speak method 
// bind to a click handler. So whenever we click a link
// it'll meow in the console

// WARNING, this will not work.
Animal.prototype.speak = function() {
  $("a").click(function() {
    console.log(this.sound);
  });
}

Scope!

// JavaScript has functional scope.
// `this` will no longer be in scope within
// a child function.

// How do we get around that?

Animal.prototype.speak = function() {
  var that = this;
  $("a").click(function() {
    console.log(that.sound);
  });
}

cat.speak(); //=> binds to links
// $(this) creates a jQuery object
// for the element that moves into scope
// on each iteration.


$("a").each(function() {
  $(this).css("color", "red");
})
$(".box.redbox").click(function() {
  $(this).addClass("purplebox");
});

Digression on a digression. Scope is really important

// we use var to maintain scope.
// variables without the `var` keyword are global

var myFunction = function() {
  var val = 10;
}
myFunction();

console.log(val);

//=> ReferenceError: val is not defined
// we use var to maintain scope.
// variables without the `var` keyword are global

var myFunction = function() {
  // no var keyword!
  // We created a global variable.
  // Avoid doing this!
  val = 10;
}
myFunction();

console.log(val);

//=> 10
// However,
// Inner functions always get access to
// outer function variables.
// This is called "closure"
// Because the outer function "closes over"
// the inner function

var outer = function() {
  var val = 10;
  var inner = function() {
    console.log(val);
  }
  inner();
}

outer();
//=> 10;

Why do we crave `closure`?

// we'll "close over" the kind variable,
// when creating a new calculator
// so it will always do that operation, even
// after that variable is gone forever!
var createCalculator = function(kind) {
  var operation = kind;
  return function(val1, val2) {
    if (operation === "add") {
      return val1 + val2;
    }
    if (operation === "subtract") {
      return val1 - val2;
    }
  }
}

var adder = createCalculator("add")
adder(1, 2)
//=> 3

Putting it together, we can figure out how jQuery's $ function works

var $ = function(selector) {
  // get selector
  var els = document.querySelectorAll(selector);
  var methods = {
    click : function(cb) {
      for (var i = 0; i < els.length; i++) {
        els[i].addEventListener("click", cb, false);
      }
      return this;
    },
    hide : function() {
      for (var i = 0; i < els.length; i++) {
        els[i].style.display = "none";
      }
      return this;  
    },
    show : function() {
      for (var i = 0; i < els.length; i++) {
        els[i].style.display = "block";
      }
      return this;
    }
  }
  return methods;
}

AJAX

Asynchronous JAvascript with XML. (Now usually JSON)

Bring remote data into your web page

The Facebook API

http://graph.facebook.com/ashaw

{
   "id": "2902652",
   "name": "Al Shaw",
   "first_name": "Al",
   "last_name": "Shaw",
   "link": "https://www.facebook.com/ashaw",
   "username": "ashaw",
   "gender": "male",
   "locale": "en_US"
}

// JSON is just JavaScript Objects
$.getJSON(url, callback)

// Notice we're not creating a jQuery object,
// we're using a jQuery "class method."
// Remember prototypes
var myElement = $("#target");

myElement.hide(); // these are "instance methods"
myElement.show(); // We have "instantiated" a new jQuery object,
                  // much like our Animal class, we're operating
                  // on one instance of that class.
// `getJSON` is a class method, meaning it's part of jQuery, but
// not a jQuery object. So we call it with $.getJSON.

var profile;

$.getJSON("http://graph.facebook.com/ashaw?callback=?", function(resp) {
  profile = resp;
});

console.log(profile.first_name);
//=> Al

Let's dynamically add some Facebook data to a web page

// The Markup

<h1></h1>
<a href="#">Click here to see my profile</a>

// Let's stick real data in that HTML

$(document).ready(function() {
  var url = "http://graph.facebook.com/ashaw"
  $.getJSON(url + "?callback=?", function(resp) {
    $("h1").html(resp.first_name);
    $("a").attr("href", resp.link)
  });
});

<h1>Al</h1>
<a href="https://www.facebook.com/ashaw">Click here to see my profile</a>

Let's build an app that gives you a full name from a username

<input type="text" id="username" />
<input type="submit" id="submit" />
<p id="fullname"></p>

$(document).ready(function() {
  $("#submit").click(function() {
    var username = $("#username").val();
    $.getJSON("http://graph.facebook.com/" + 
               username + "?callback=?", function(resp) {
      $("#fullname").html(resp.first_name + " " + resp.last_name);
    });
  });
});

What if the username doesn't exist? Error checking!

$(document).ready(function() {
  $("#submit").click(function() {
    var username = $("#username").val();
    $.getJSON("http://graph.facebook.com/" + 
               username + "?callback=?", function(resp) {
      if (resp.error) {
        $("#fullname").html("That username doesn't exist");
      } else {
        $("#fullname").html(resp.first_name + " " + resp.last_name);
      }
    });
  });
});

More complicated apps

FB makes this easier by giving us a JS SDK.

Let's use it to get stuff that requires our user to be logged in!

Setting up the room

<!-- facebook needs this on the page -->
<div id="fb-root"></div>
// Load the SDK (English)
<script src="//connect.facebook.net/en_US/all.js"></script>

// Spanish/Latin America
<script src="//connect.facebook.net/es_LA/all.js"></script>
  
// put this in a script tag
FB.init({
  appId      : '429491807092112', // test app we're using for HHBA
  status     : true,
  cookie     : true,
  xfbml      : true
});

This FB app is set to work on localhost:8000

// in your code folder, on Mac or Linux
$ python -m SimpleHTTPServer

Goal: Let's build an app that tells us what our friends' favorite news sources are

Steps:
1. Get user's permission
2. Grab news feed
3. Find link domains
4. Present results

Follow along:

https://gist.github.com/3497835

Improvements?
1. More links
2. Site name instead of Domain
3. Filter out social media

OK. Your turn!

Thank you.

Al Shaw       @A_L    ALMSHAW@GMAIL.COM