Technology fundamental for d3.js


A tutorial by Kanit "Ham" Wongsuphasawat

Interactive Data Lab, University of Washington

@kanitw / kanitw.yellowpigz.com

Notes

  • HTML, CSS and SVG examples are all codepens, which you can click edit to play with.
  • You can also use inspector (⌘⎇I in Chrome) to inspect examples.
  • Also use Javascript console (⌘⎇J in Chrome) to try Javascript code examples.

HTML

Hypertext Markup Language

Plain Text

Use HTML to markup

html, body, h1, p, strong, em, a, img

See the Pen wBmEu by Kanit Wongsuphasawat (@kanitw) on CodePen

See the Pen wBmEu by Kanit Wongsuphasawat (@kanitw) on CodePen

HTML: div, span + ID, Class

<div> , <span>

See the Pen jAHsK by Kanit Wongsuphasawat (@kanitw) on CodePen

See the Pen jAHsK by Kanit Wongsuphasawat (@kanitw) on CodePen

More Tags

  • list (ul, ol, li), hr, br, form, input, select, iframe
  • See w3schools's quick list of the most commonly used HTML tags
  • Or learn more at Mozilla Develop Network's HTML tutorial.
  • DOM

    • A convention for representing and interacting with objects in HTML, XHTML and XML documents.
    • Nodes of every document are organized in a tree structure, called the DOM tree
      • For example, use inspector to see this file's source.
    • Provides API for modify its content using language such as Javascript
    ### CSS #### Cascading Stylesheet

    CSS Selectors

    Query the DOM Tree

    See the Pen xDIbe by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen xDIbe by Kanit Wongsuphasawat (@kanitw) on CodePen

    See also: CSS Properties – Webmonkey and CSS Selectors on NetTuts

    CSS: Box Model, Position

    The default position is position: static;

    See the Pen eLlKj by Kanit Wongsuphasawat (@kanitw) on CodePen

    CSS: Position

    relative adjust the element's position, without changing layout

    See the Pen Fnulb by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen Fnulb by Kanit Wongsuphasawat (@kanitw) on CodePen

    CSS: Position

    absolute taken out of the flow and thus takes up no space when placing other elements. The absolutely positioned element is positioned relative to nearest positioned ancestor. If a positioned ancestor doesn't exist, the initial container is used.

    See the Pen HDfgn by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen HDfgn by Kanit Wongsuphasawat (@kanitw) on CodePen

    CSS: Position

    absolute under relative

    See the Pen EyaHr by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen EyaHr by Kanit Wongsuphasawat (@kanitw) on CodePen

    CSS: Short Form

                  
                    background-color: #000; background-image: url(images/bg.gif); background-repeat: no-repeat; background-position: top right;
                  
                

    Can be shortened to:

                  
                    background: #000 url(images/bg.gif) no-repeat top right;
                  
                

    CSS: Include

    Inline:

                  
                    
                  
                
                  
                    
    ...

    Include:

                  
                    
                  
                

    CSS: Grids

    Grid is one of the most commonly used graphic design concept.

    For instance, see bootstrap grid's examples

    Sass

    Variable, Nesting, Partials, Import, Mixins, Inheritance, Operators

    
    /* variable, operator */
    
    $font-stack:    Helvetica, sans-serif;
    $primary-color: #333;
    
    body {
      font: 0.8*100% $font-stack;
      color: $primary-color;
    }
    
    /* nesting */
    nav {
      ul {
        margin: 0;
        padding: 0;
        list-style: none;
      }
    
      li { display: inline-block; }
    
      a {
        display: block;
        padding: 6px 12px;
        text-decoration: none;
      }
    }
    
    /* mixin */
    
    @mixin border-radius($radius) {
      -webkit-border-radius: $radius;
         -moz-border-radius: $radius;
          -ms-border-radius: $radius;
           -o-border-radius: $radius;
              border-radius: $radius;
    }
    
    .box { @include border-radius(10px); }
                

    Less is a another option.

    Compass

    a collection of reusable mixins for designers

    Example: inline-block

    
    @mixin inline-block($alignment: $inline-block-alignment) {
      @if $legacy-support-for-mozilla {
        display: -moz-inline-stack;
      }
      display: inline-block;
      @if $alignment and $alignment != none {
        vertical-align: $alignment;
      }
      @if $legacy-support-for-ie {
        *vertical-align: auto;
        zoom: 1;
        *display: inline;
      }
    }
              

    CSS: Learn more!

    SVG

    Scalable Vector Graphics

    SVG

    See the Pen tpmfo by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen tpmfo by Kanit Wongsuphasawat (@kanitw) on CodePen

    SVG + CSS

    See the Pen upxsq by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen upxsq by Kanit Wongsuphasawat (@kanitw) on CodePen

    SVG: Polygon, Polyline

    Use coordinates to specify path

    See the Pen GfxFD by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen GfxFD by Kanit Wongsuphasawat (@kanitw) on CodePen

    SVG: Path

    M x y – Move to (x,y)

    m dx dy – Move by (dx,dy)

    L x y – Line to (x,y) (or l dx dy)

    H x, V y – draw horizontal and vertical lines

    Z, z close path

    See also: Curves Commands

    SVG: Path Example

    See the Pen Dbrau by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen Dbrau by Kanit Wongsuphasawat (@kanitw) on CodePen

    SVG: Group, Title & Transform

    • Transform example: translate
    • Use title for tooltip

    See the Pen Dbuhd by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen Dbuhd by Kanit Wongsuphasawat (@kanitw) on CodePen

    SVG: More Transforms

    rotate, scale, skewX, skewY

    See the Pen cprgG by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen cprgG by Kanit Wongsuphasawat (@kanitw) on CodePen

    See more Transformation

    SVG: No-Layer

    Painter's Algorithm: any pixel-paint applied later obscure any earlier paint and therefore appear to be "in front".

    See the Pen linFm by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen linFm by Kanit Wongsuphasawat (@kanitw) on CodePen

    SVG: Transparency

    rgba or opacity

    See the Pen AFzvx by Kanit Wongsuphasawat (@kanitw) on CodePen

    See the Pen AFzvx by Kanit Wongsuphasawat (@kanitw) on CodePen

    SVG: Learn more!

    Javascript

    ### Javascript * Originally developed as a prototype language for web browser (Client-side) * Now used in server-side (Node.js) as well. * Not related to Java, just named similarly for marketing purpose. * C style syntax but got inspiration from Functional programming * `for`, `while`, `continue`, `break`, `if`/`else`, `switch` are similar to C * operators (`+`,`-`,`*`,`/`,`%`) are also similar (except `==`,`!=`,`||`)

    Client-side Javascript: Inline/Include

    Inline

    
    
              

    Include

    
    
              

    Data Types

    • Numbers - 42, 3.14159
    • Logical - true, false
    • Strings - "Hello", 'Hello'
    • null
    • undefined
    • Objects
    • functions

    See also Values, Variable, Literals–MDN

    Variables

    
    var a;
    console.log("The value of a is " + a); // logs "The value of a is undefined"
    console.log("The value of b is " + b); // throws ReferenceError exception
    b = 5 // declare global variable  ... equivalent to window.b = 5
    console.log(b, window.b) // 5, 5
              

    Javascript uses dynamic typing.

                
    x = "The answer is " + 42; // "The answer is 42"
    "37" - 7; // 30
    "37" + 7; // "377"
    "1.1" + "1.1"; //= "1.11.1"
    (+"1.1") + (+"1.1"); // 2.2
    +"1.1" // 1.1 "+" operator converts string to number
                
              

    Tips: || operator can return Object too.

    
    y = null || "String"
    y // "String"
              

    Control Flow

    C-Style `for`, `while`, `continue`, `break`, `if`/`else`, `switch/case`

    
    for(i=0; i<10; i++){
      if (condition) {
          statement_1_runs_if_condition_is_true();
          break;
      } else {
          statement_2_runs_if_condition_is_false();
          continue;
      }
    }
              

    (I'm not showing while, switch/case here for brevity.)

    ### Object * An object in javascript is an associative array of property names (Strings) and values (Objects). * Everything except null and undefined) can be treated as objects. * Object can be used as hashmaps. * Object can be created using (a) literals (b) new

    Objects: Literals & new

    //create object using an object literal
    var apple = {
      // quotes not required for a property name
      state: "CA",
      // unless the name contains space(s) or precedes with number or the name is reserved word
      "famous founder": "Steve Jobs",
      // property value can be any type including function
      getCity: function(){return "Cupertino";},
      // nested object
      boards: { "CEO": "Tim Cook"}
    };
    apple.state; // "CA"
    apple["state"]; // "CA"
    apple.getCity(); // "Cupertino"
    apple['getCity'](); // "Cupertino"
    apple.boards.CEO // "Tim Cook"
    
    //create object using new instead
    var microsoft = new Object();
    microsoft.state = "WA";
    microsoft['famous founder'] = "Bill Gates";
    microsoft.getCity = function(){ return "Redmond";};
            

    for .. in

    Careful: use hasOwnProperty to check

    
    var obj = {a:1, b:2, c:3}, key;
    Object.prototype.crazy = 4;
    for(key in obj){
      if(obj.hasOwnProperty(key)){ //avoid the inherited obj.crazy=4
        console.log(key, obj[key]); // "a, 1" "b, 2", "c, 3"
      }
    }
              

    Arrays

    
    var numbers = [ 5, 10, 15, 20, 25];
    numbers[1] // 10
    numbers[2] // 15
    numbers.length = 5
    2 in numbers // true
    5 in numbers // false
    numbers.a = 5 // Array is an object
    numbers.a // 5
    'a' in numbers // true
              
    
    var numbers = [ 5, 10, , 20, 25, , ];
    numbers[1] // 10
    numbers[2] // undefined
    numbers.length //6 last empty comma is automatically ignored
              
              
    // array with multiple types of values
    var mashup = [ 1,3, 4.5, 5.6, "string", null, undefined, true ];
                
              

    Function

    First class object...

    
                function foo(a1, a2){
                  // code
                  console.log(a1+a2);
                }
    
              
    same as
    
                var foo = function(a1, a2){
                  // code
                  console.log(a1+a2);
                };
              
    
                foo(a1,a2); // call
              
    
                function g(f){ f(1,2); }
                g(foo) // 3
              

    See also: Arguments Objects

    Scope

    • Javascript has function level scope, not block level scope.
    • The inner function full access to all the variables and functions defined inside the outer function. But the converse is not true.
    
    var name = "Andy"
    var pet = function(name) {      // The outer function defines a variable called "name"
          var getName = function() {
            return name;            // The inner function has access to the "name" variable of the outer function, which is "Vivie" in this case.
          }
    
          return getName;           // Return the inner function, thereby exposing it to outer scopes
        };
    var myPet = pet("Vivie");
    myPet();                        // Returns "Vivie"
    console.log(name);              // "Andy"
              

    Scope

    Javascript has function level scope, not block level scope.

    
    var x = 1;
    {
      var x = 2;
    }
    alert(x); // outputs 2
              

    Scope: Hoisting

    
    console.log(x === undefined); // logs "true"
    var x = 3;
              

    is equivalent to

    
    var x;
    console.log(x === undefined); // logs "true"
    x = 3;
              

    IIFE

    Immediately Invoked Function Expression

    
    var elems = document.getElementsByTagName( 'a' );
    
    for ( var i = 0; i < elems.length; i++ ) {
    
      elems[ i ].addEventListener( 'click', function(e){
        e.preventDefault();
        alert( 'I am link #' + i );
      }, 'false' );
    }
                    

    The value of `i` never gets locked in. Thus, every link, when clicked (well after the loop has finished executing), alerts the total number of elements.

    
    var elems = document.getElementsByTagName( 'a' );
    
    for ( var i = 0; i < elems.length; i++ ) {
    
      (function( lockedInIndex ){
        elems[ i ].addEventListener( 'click', function(e){
          e.preventDefault();
          alert( 'I am link #' + lockedInIndex );
        }, 'false' );
      })( i );
    
    }
                    

    This works, because inside the IIFE, the value of `i` is locked in as `lockedInIndex`.

    See also: Ben Alman's Post

    IIFE: Anonymous Namespaces

    Use IIFE to avoid namespace clashing!

    
    (function() {
        // a self contained "namespace"
    
        // PUT YOUR NONE PUBLIC SCRIPT HERE
        // ...
    
        window.foo = function() {
            // an exposed closure
        };
    
    })(); // execute the function immediately
              

    For public namespace, use nested objects. See d3.js, for example.

    this

    
    var test = {};
    this; // this = global object aka window
    foo(); // this = global object again
    test.foo(); // this = test
    new foo(); // this = newly created object
              

    Explicity Setting of this

    
    function foo(a, b, c) {
      // this = bar here when foo is called from apply and call below
    }
    var bar = {};
    foo.apply(bar, [1, 2, 3]); // array will expand to the below
    foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
              

    Source: Javascript Garden

    "that"

    
    Foo = {a:1};
    Foo.method = function() {
        var that = this;
        function test() {
            // Use that instead of this here
            // because here this is set to the global object
            console.log(this, that); // Window, {a:1, method: function}
        }
        test();
    }
              

    OOP in Javascript: using Constructor

    
    function Person(gender) {
      this.gender = gender;
    }
    
    Person.prototype.sayHello = function(){
      alert ('hello');
    };
    
    var person1 = new Person('Male'), person2 = new Person('Female');
    
    // call the Person sayHello method.
    person1.sayHello(); // hello
            

    Source: Mozilla

    OOP in Javascript: Inheritance

    Extend Person

    
    function Person(gender) {
      this.gender = gender;
    }
    Person.prototype.sayHello = function(){
      alert ('hello');
    };
            
    
    // inherit Person
    Student.prototype = new Person();
    
    // correct the constructor pointer because it points to Person
    Student.prototype.constructor = Student;
    
    // replace the sayHello method
    Student.prototype.sayHello = function(){
      alert('hi, I am a student');
    }
    
    var student1 = new Student();
    student1.sayHello();
    
    alert(student1 instanceof Person); // true
    alert(student1 instanceof Student); // true
              

    Prototypal Inheritance

    
    var o = {a: 1};
    
    // The newly created object o has Object.prototype as its [[Prototype]]
    // o has no own property named 'hasOwnProperty'
    // hasOwnProperty is an own property of Object.prototype. So o inherits hasOwnProperty from Object.prototype
    // Object.prototype has null as its prototype.
    // o ---> Object.prototype ---> null
    
    var a = ["yo", "whadup", "?"];
    
    // Arrays inherit from Array.prototype (which has methods like indexOf, forEach, etc.)
    // The prototype chain looks like:
    // a ---> Array.prototype ---> Object.prototype ---> null
    
    function f(){
      return 2;
    }
    
    // Functions inherit from Function.prototype (which has methods like call, bind, etc.)
    // f ---> Function.prototype ---> Object.prototype ---> null
              

    source & see also: prototype chain

    Module Pattern & Private Variable

    Module Pattern use scope to make a private variable

    
    function Counter(start) {
        var count = start;
        return {
            increment: function() {
                count++;
            },
    
            get: function() {
                return count;
            }
        }
    }
    
    var foo = Counter(4);
    foo.increment();
    foo.get(); // 5
    foo.count // undefined ... outsider can't access count directly
              

    Using Object.create

    === and ==

    • The == operator will compare for equality after doing any necessary type conversions (with very weird conversion rules).
    • The === operator will not do the conversion, so if two values are not the same type === will simply return false.
                
    '' == '0'           // false
    0 == ''             // true
    0 == '0'            // true
    
    false == 'false'    // false
    false == '0'        // true
    
    false == undefined  // false
    false == null       // false
    null == undefined   // true
    
    ' \t\r\n ' == 0     // true
                
              
    Never use the evil twins.
    Instead, always use === and !==.
    See also: http://stackoverflow.com/questions/359494/does-it-matter-which-equals-operator-vs-i-use-in-javascript-comparisons

    Javascript: DOM

    As mentioned earlier, DOM provided javascript API. You should at least know about:

    JSON

    Javascript Object Notation

    Derived from Javascript as an XML alternative for storing data.

    JSON

    Javascript Object Notation

    • JSON requires have double quote(") around keys
    • JSON doesn't support undefined, expressions, functions, and comments
    
    JSON.parse('{"a":null}'); // {a:null}
    JSON.parse('{"a":undefined}'); // SyntaxError: Unexpected token u
    JSON.parse('{"a":function(){return 'a';}}'); // SyntaxError: Unexpected identifier
              

    Syntax Alternatives

    Some people like syntax alternative that compile into javascript such as Coffeescript, MS TypeScript.

    ### Libraries * *[Lo-Dash](http://lodash.com)* – Utility library (arguably a better fork of [Underscore](http://underscorejs.org/)) – See a [tutorial](http://tech.pro/tutorial/1611/functional-javascript) * *[jQuery](http://jquery.com/)* – easy DOM element selections, traversal and manipulation. * However, less useful for visualization since d3 offers similar features * [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) Frameworks: [Backbone.js](http://backbonejs.org), [Angular.js](http://angularjs.org), [Meteor.js](http://meteor.com)

    Javascript: Learn More

    Workflow & Tools

    Q&A