Document Object Model

- tree like structure created by browsers so we can quickly find HTML elements us JavaScript
- HTML loaded piece by piece into the DOM
- inside the DOM, HTML elements become 'nodes' which have relationships with one another

In order to interact with the DOM, all browsers use JS
- however, each browser has a slightly different DOM interface. If our JS uses jQuery to interact with the DOM then it will work on most all modern browsers

Basic jQuery usage, code put inside jQuery function:
jQuery([code]);
jQuery("h1"); // instead of writing jQuery can simply use the $ sign
$("p");
$("h1").text();  // text("Update here") is a method offered by jQuery

The DOM ready event - to ensure jQuery only runs after the DOM ready event has been triggered:

$(document).ready(function(){
  $("h1").text("update me");
});

Will only run this code one the DOM is 'ready'

Selectors

Can use ID and Class to select elements of the DOM

CSS jQuery
p { … } $("p");
#container { … } $("#container");
.articles { … } $(".articles");

$("#parent li");
$("#parent > li); // is the direct child selector
$("#one, #two); // will select both

Traversing

$("#class").find("li"); // will find (traverse) all list items underneath #class
$("li").last(); or $("li").first(); last or first method

Method chaining:
$("li").first().next();
$("li").last().prev();

Can also traverse up and down the DOM:
.parent();
.children();

Working with the DOM

var price = $('<p>From $399.99</p>'); // will create new DOM node and send into price variable

This doesn't add to DOM yet.  To add to DOM use:
- append()
- prepend()
- after()
- before()
$('.vacation').append(price);
$('button').remove(); 
OR
- appendTo()
- prependTo()
- .insertAfter()
- .insertBefore()
in which case:
price.appendTo($('.vacation'));

Acting on interaction

jQ Object Methods:
- .on(, )

$(document).ready(function(){
  $('button').on('click', function(){
  // runs when button is clicked
  });
}); 

Refactor using Traversing

if use 'this', we are referring to the item that triggered the event:
$(this).after(price);
$(this).remove();
$(this).closest('.vacation').append(price); // will walk up DOM and append price

Attributes

data-price
data- is a HTML5 attribute you can add to provide additional information about elements on the page
To interact:
.data(<name>)
To set:
.data(<name>, <value>)

Event delegation

$('.vacation').on('click', 'button', function() {} ); // can specify the class 'button' in the object method

Filtering

$('.vacation').filter('.onsale'); // will find elements with a class .vacation and .onsale

Class Manipulation

- .addClass()
- .removeClass()
- toggleClass()
- .hasClass()
- no .class, just 'class'

Listening on DOM events

jQuery Object Methods

.slideDown()
.slideUp()
.slideToggle()
.fadeIn()
.fadeOut()
.fadeToggle()
.val(<new value>) will set input value
.val() will get input value

alert($('li').length); // will alert how many li nodes are on the page

Mouse events

.on('click', 'focusin', 'mousedown', 'mousemove', 'mouseover', 'mouseenter', 'dblclick', 'focusout', 'mouseup', 'mouseout', 'mouseleave')

$('.photos').on('mouseenter', 'li', function() { } );

Keyboard events

.on('keypress', 'keydown', 'keyup')

Form events

.on('blur', 'select', 'change', 'focus', 'submit')

Adding a plus to the start of an assignment statement that equals a string will return a number:
var price = +$(this).closest('.vacation').data('price');

Event functions

$('.vacation').on('click', '.expand', function(event) {
  event.stopPropagation(); - the browser will handle the click event but will prevent it from 'bubbling up'
  event.preventDefault(); - the click event will 'bubble up' but the browser won't handle it
  ...
});

CSS

.css(<attr>, <value>)
.css(<attr>)
.css(<object>)

Cleanest is to send in a JS object:
$(this).css({'background-color': '#ffffff', 'border-color': '1px solid #967'});

.show()
.hide()

$(this).find('.price').show();
- a good way to do this is to add the style to the css, and then .addClass()

Animation

.animate(<object>, speed);
- takes in a JS object, will adjust a CSS property pixel by pixel in order to animate it:
$(this).animate({'top': '-10px'}, 200/'fast');

Can animate with .hasClass();
- can also use CSS transitions

AJAX

Asynchronus JavaScript And XML
- communicate with the web server without doing a full page refresh

jQuery Ajax Method

$.ajax(url[, settings])

Success callback:

$('.confirmation').on('click', 'button', function(){
  $.ajax('confirmation.html', {
    success: function(response) {
      $('.ticket').html(response).slideDown();
      },
      data: { "confNum": 1234 } {
      // A JS object which added to the response URL
      }
  });
});

Shorthand method:
$.get(url, success)

$('.confirmation').on('click', 'button', function(){
  $.get('confirmation.html', function(response) {
    $('.ticket').html(response).slideDown();
  });
}); 

Failed callbacks:
- runs the error callback if there is a timeout, about, or server error

$('.confirmation').on('click', 'button', function(){
  $.ajax('confirmation.html', {
    success: function(response) {
      $('.ticket').html(response).slideDown();
    },

    data: { "confNum": 1234 } {
      // A JS object which added to the response URL
    },

    error: function (request, errorType, errorMessage) {
      alert('Error: ' + errorType + ' with message: ' + errorMessage);
    },

    timeout: 3000,

    beforeSend: function () {
      $('.confirmation').addClass('is-loading');
     },

    complete: function() { 
      $('.confirmation').removeClass('is-loading');
    }
  });
}); 

Event delegation

- event handler may not run against particular css class if that class doesn't exist yet because AJAX hasn't run
- need to use event delegation, or cleaner call:
$('.confirmation').on('click', '.view-boarding-pass', function(){ ... });

Using Javascript Objects

var confirmation = {
  init: function() {
  // all existing event handlers, this code runs all the code that was in document ready function
  }
};

when want to call init, place in document ready function and call confirmation.init()

$(document).ready(function(){
  confirmation.init();
});

- limited to 1 confirmation per page
- may want to use a function instead

Using Javascript Functions

console.log(message);

el refers to a jQuery Object:

function Tour(el) {

}

function Vacation(destination) {

}

$(document).ready(function(){
  var paris = new Vacation('Paris');
  var london = new Vacation('London');
});

AJAX Post / forms

$('form').on('.submit', function(e) {
  e.preventDefault(); // prevents refreshing the page, and submitting the form
  $.ajax('/book', {
    type: 'POST',
    data: { "destination": $('#destination').val(), "quantity": $('#quantity').val() }
    // OR
    data: $('form').serialize()
  });
});

serialize() // can be used to merge all form fields for a submission

JSON

- JavaScript Object Notation
- standard way to format data

$('form').on('.submit', function(e) {
  e.preventDefault(); 
  var form = $(this);
  $.ajax($('form').attr('action'), {
    type: 'POST',
    dataType: 'json', // parse the response as JSON
    contentType: 'application/json', // ask the server to response with JSON
    data: form.serialize(),
    success: function(result) {
      form.remove();
      var msg = $("<p></p>");
      msg.append("Destination: " + result.location + ". ");
      msg.append("Price: " + result.totalPrice + ". ");
      msg.append("Nights: " + result.totalNights + ". ");
      msg.append("Confirmation: " + result.confirmation + ". ");
      $('#vacation').hide().html(msg).fadeIn();
  });
});

The JSON response from the server will be automatically created into a JS Object.  This is used to redender the success response.

Can also de-dup that both URL is same in HTML and JS '/book'.

attr(<attribute>)
attr(<attribute>, <value>)

Looping over multiple objects in an array

$.each() jQuery method can iterate through a data array
$.each(collection, function(<index of the array>, <object>) { }

Get JSON function

$.getJSON(url, success);

Using Map

$.map(collection, function(<item>, <index>) { } );
// collection is similar to an array, item each item in collection
// map returns an array modified by what is returned in the function passed as an argument

.detach() removes an element from the DOM, preserving all data and events.  This is useful to minimise DOM insertions with multiple html elements

Special Events

Off Method - opposite to on method
off(<event name>)

Events namespacing - adding labels on the end of click handlers

$(.'button').on('click.image', ... );
$('button').off('click.image', ... );

trigger(<event name>)
- will trigger event via JS rather than interacting with DOM
$('button').trigger('click');

JQuery Plugins

fn makes plugin available to all jQuery objects:

$.fn.methodName = function() {
  console.log();
};

To call:
$('.vacation').methodName();  // this will method-ify all vacations at once

each()
- can call on each as an array
$.extend(target[, object1][, objection])
- takes in two or more JS objects and combines them

Promises

- all AJAX requests return a object of type promise
- can call methods on promise object that give interesting behaviour
promise.done(function(result){ ... });

API & jQuery

Get

jQuery.get( '/api/', function( data, textStatus, jqXHR ) {
  console.log( 'Get response:' );
  console.dir( data );
  console.log( textStatus );
  console.dir( jqXHR );
});

Post

jQuery.post( '/api/', {
  'title': 'JavaScript the good parts',
  'author': 'Douglas Crockford',
  'releaseDate': new Date( 2008, 4, 1 ).getTime()
}, function(data, textStatus, jqXHR) {
  console.log( 'Post response:' );
  console.dir( data );
  console.log( textStatus );
  console.dir( jqXHR );
});

Get by ID

jQuery.get( '/api/4f95a8cb1baa9b8a1b000006', function( data, textStatus, jqXHR ) {
  console.log( 'Get response:' );
  console.dir( data );
  console.log( textStatus );
  console.dir( jqXHR );
});

Put

jQuery.ajax({
  url: '/api/4f95a8cb1baa9b8a1b000006',
  type: 'PUT',
  data: {
    'title': 'JavaScript The good parts',
    'author': 'The Legendary Douglas Crockford',
    'releaseDate': new Date( 2008, 4, 1 ).getTime()
  },
  success: function( data, textStatus, jqXHR ) {
    console.log( 'Put response:' );
    console.dir( data );
    console.log( textStatus );
    console.dir( jqXHR );
  }
});

Delete

jQuery.ajax({
  url: '/api/4f95a5251baa9b8a1b000001',
  type: 'DELETE',
  success: function( data, textStatus, jqXHR ) {
    console.log( 'Delete response:' );
    console.dir( data );
    console.log( textStatus );
    console.dir( jqXHR );
  }
});