Slide 1

Slide 1 text

I know jQuery. Now what? Remy Sharp • @rem

Slide 2

Slide 2 text

7 years ago...

Slide 3

Slide 3 text

7 years ago... Actually, me 7 years ago...

Slide 4

Slide 4 text

$ =

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Ajax Grokage Ajax + me WAT?

Slide 8

Slide 8 text

function getXmlHttpRequest() { var xhr; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { xhr = false; } } } return xhr; } // disclaimer: John's jQuery version is a lot more elegant!

Slide 9

Slide 9 text

Back to the Future

Slide 10

Slide 10 text

querySelectorAll

Slide 11

Slide 11 text

var $ = document.querySelectorAll.bind(document); Element.prototype.on = Element.prototype.addEventListener; $('#somelink')[0].on('touchstart', handleTouch);

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

When I use jQuery

Slide 14

Slide 14 text

No mustard cu ing: I include jQuery.

Slide 15

Slide 15 text

if (querySelector in document && localStorage in window && addEventListener in window) { // bootstrap the JavaScript app }

Slide 16

Slide 16 text

Quick 'n Dirty

Slide 17

Slide 17 text

Sans jQuery

Slide 18

Slide 18 text

document.ready

Slide 19

Slide 19 text

.attr()

Slide 20

Slide 20 text

$('input').on('change', function () { var value = $(this).attr('value'); alert('The new value is' + value); });

Slide 21

Slide 21 text

$('input').on('change', function () { var value = this.value; alert('The new value is' + value); });

Slide 22

Slide 22 text

$('a').attr('href') a.getAttribute('href') a.href

Slide 23

Slide 23 text

$('body').addClass('hasJS');

Slide 24

Slide 24 text

document.body.className = 'hasJS';

Slide 25

Slide 25 text

Classy

Slide 26

Slide 26 text

body.className += ' hasJS'

Slide 27

Slide 27 text

body.classList.add('hasJS')

Slide 28

Slide 28 text

body.classList.remove('hasJS')

Slide 29

Slide 29 text

body.classList.toggle('hasJS')

Slide 30

Slide 30 text

body.classList.add('foo', 'bar')

Slide 31

Slide 31 text

body.classList.contains(''); // SyntaxError: DOM Exception 12 :(

Slide 32

Slide 32 text

data

Slide 33

Slide 33 text

el.dataset.user = JSON.stringify(user); el.dataset.score = score;

Slide 34

Slide 34 text

ax

Slide 35

Slide 35 text

function request(type, url, opts, callback) { var xhr = new XMLHttpRequest(); if (typeof opts === 'function') { callback = opts; opts = null; } xhr.open(type, url); // serialise post data if (type === 'POST' && opts) { // } xhr.onload = function () { callback(JSON.parse(xhr.response)); }; xhr.send(opts ? fd : null); } var get = request.bind(this, 'GET'); var post = request.bind(this, 'POST');

Slide 36

Slide 36 text

function request(type, url, opts, callback) { var xhr = new XMLHttpRequest(); if (typeof opts === 'function') { callback = opts; opts = null; } xhr.open(type, url); // serialise post data if (type === 'POST' && opts) { // } xhr.onload = function () { callback(JSON.parse(xhr.response)); }; xhr.send(opts ? fd : null); } var get = request.bind(this, 'GET'); var post = request.bind(this, 'POST'); xhr.onload = function () { callback(JSON.parse(xhr.response)); };

Slide 37

Slide 37 text

function request(type, url, opts, callback) { var xhr = new XMLHttpRequest(); if (typeof opts === 'function') { callback = opts; opts = null; } xhr.open(type, url); // serialise post data if (type === 'POST' && opts) { // } xhr.onload = function () { callback(JSON.parse(xhr.response)); }; xhr.send(opts ? fd : null); } var get = request.bind(this, 'GET'); var post = request.bind(this, 'POST');

Slide 38

Slide 38 text

•CORS •Progress events •Upload progress events •Different posting types •Using FormData

Slide 39

Slide 39 text

fffffffffforms!

Slide 40

Slide 40 text

Slide 41

Slide 41 text

Slide 42

Slide 42 text

Slide 43

Slide 43 text

Style & animation

Slide 44

Slide 44 text

CSS > JS

Slide 45

Slide 45 text

CSS > JS

Slide 46

Slide 46 text

CSS > JS (for CSS, duh)

Slide 47

Slide 47 text

Ss

Slide 48

Slide 48 text

Bad: .css

Slide 49

Slide 49 text

Good: .addClass

Slide 50

Slide 50 text

Gooderer: .className

Slide 51

Slide 51 text

If it's native to the browser, let the browser get on with it's job.

Slide 52

Slide 52 text

Animation

Slide 53

Slide 53 text

setInterval VS. requestAnimationFrame

Slide 54

Slide 54 text

setInterval requestAnimationFrame

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

rAF > setInterval

Slide 57

Slide 57 text

CSS animations also uses rAF scheduling

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

Translate =

Slide 60

Slide 60 text

el.on("webkitTransitionEnd", ended); el.on("transitionend", ended); Note the the lowercase 'e' on 'end'...

Slide 61

Slide 61 text

And yes, there are plugins. 1. jQuery-Animate-Enhanced 2. jQuery.Transit

Slide 62

Slide 62 text

jQuery plugin. Just because.

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

No content

Slide 65

Slide 65 text

$.fn.fitText = function( kompressor, options ) { // Setup options var compressor = kompressor || 1, settings = $.extend({ 'minFontSize' : Number.NEGATIVE_INFINITY, 'maxFontSize' : Number.POSITIVE_INFINITY }, options); return this.each(function(){ // Store the object var $this = $(this); // Resizer() resizes items based on the object width divided by the compressor * 10 var resizer = function () { $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize))); }; // Call once to set. resizer(); // Call on resize. Opera debounces their resize by default. $(window).on('resize orientationchange', resizer); }); };

Slide 66

Slide 66 text

$.fn.fitText = function( kompressor, options ) { // Setup options var compressor = kompressor || 1, settings = $.extend({ 'minFontSize' : Number.NEGATIVE_INFINITY, 'maxFontSize' : Number.POSITIVE_INFINITY }, options); return this.each(function(){ // Store the object var $this = $(this); // Resizer() resizes items based on the object width divided by the compressor * 10 var resizer = function () { $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize))); }; // Call once to set. resizer(); // Call on resize. Opera debounces their resize by default. $(window).on('resize orientationchange', resizer); }); }; 1. extend

Slide 67

Slide 67 text

$.fn.fitText = function( kompressor, options ) { // Setup options var compressor = kompressor || 1, settings = $.extend({ 'minFontSize' : Number.NEGATIVE_INFINITY, 'maxFontSize' : Number.POSITIVE_INFINITY }, options); return this.each(function(){ // Store the object var $this = $(this); // Resizer() resizes items based on the object width divided by the compressor * 10 var resizer = function () { $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize))); }; // Call once to set. resizer(); // Call on resize. Opera debounces their resize by default. $(window).on('resize orientationchange', resizer); }); }; 1. extend 2. each

Slide 68

Slide 68 text

$.fn.fitText = function( kompressor, options ) { // Setup options var compressor = kompressor || 1, settings = $.extend({ 'minFontSize' : Number.NEGATIVE_INFINITY, 'maxFontSize' : Number.POSITIVE_INFINITY }, options); return this.each(function(){ // Store the object var $this = $(this); // Resizer() resizes items based on the object width divided by the compressor * 10 var resizer = function () { $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize))); }; // Call once to set. resizer(); // Call on resize. Opera debounces their resize by default. $(window).on('resize orientationchange', resizer); }); }; 1. extend 2. each 3. width

Slide 69

Slide 69 text

$.fn.fitText = function( kompressor, options ) { // Setup options var compressor = kompressor || 1, settings = $.extend({ 'minFontSize' : Number.NEGATIVE_INFINITY, 'maxFontSize' : Number.POSITIVE_INFINITY }, options); return this.each(function(){ // Store the object var $this = $(this); // Resizer() resizes items based on the object width divided by the compressor * 10 var resizer = function () { $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize))); }; // Call once to set. resizer(); // Call on resize. Opera debounces their resize by default. $(window).on('resize orientationchange', resizer); }); }; 1. extend 2. each 3. width 4. css

Slide 70

Slide 70 text

$.fn.fitText = function( kompressor, options ) { // Setup options var compressor = kompressor || 1, settings = $.extend({ 'minFontSize' : Number.NEGATIVE_INFINITY, 'maxFontSize' : Number.POSITIVE_INFINITY }, options); return this.each(function(){ // Store the object var $this = $(this); // Resizer() resizes items based on the object width divided by the compressor * 10 var resizer = function () { $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize))); }; // Call once to set. resizer(); // Call on resize. Opera debounces their resize by default. $(window).on('resize orientationchange', resizer); }); }; 1. extend 2. each 3. width 4. css 5. on

Slide 71

Slide 71 text

if (options === undefined) { options = {}; } if (options.minFontSize === undefined) { options.minFontSize = Number.NEGATIVE_INFINITY; } if (options.maxFontSize === undefined) { options.maxFontSize = Number.POSITIVE_INFINITY; } .extend becomes init default options

Slide 72

Slide 72 text

// assuming polyfill or IE9+ nodes.forEach(function (node) { // where we used `this`, we now use `node` // ... }) .each becomes regular loop

Slide 73

Slide 73 text

var resizer = function () { var width = node.clientWidth; // ... }; .width becomes .clientWidth property Note: clientWidth != .width() - but will do for our solution

Slide 74

Slide 74 text

node.style.fontSize = Math.max(...); .css becomes se ing style property

Slide 75

Slide 75 text

// assuming polyfill or IE9+ window.addEventListener('resize', resizer, false); .on becomes .addEventLister Polyfill: h ps://gist.github.com/eirikbacker/2864711

Slide 76

Slide 76 text

Idea: Why not use PE to support jQuery?

Slide 77

Slide 77 text

Recap querySelectorAll for DOM navigation Think about when to use jQuery / a library Ditch document.ready Use this.value Try .classList Really grok ajax No more JavaScript animations Maybe no-jQuery first?

Slide 78

Slide 78 text

Your turn.