Transcript
Page 1: jQuery Foot-Gun Features

Foot-Gun Featuresto Avoid in jQuery

Dave Methvin, President, jQuery Foundation

Page 2: jQuery Foot-Gun Features
Page 3: jQuery Foot-Gun Features

• We maintain jQuery code, and much more• We represent the web developer in

groups like the W3C and ECMA (JavaScript)• We encourage collaboration to avoid a

lot of "almost but not quite alike" solutions that can't play well together

Page 4: jQuery Foot-Gun Features

Let's make standards work for us, solving real problems!

Web developer needs should be expressed early in the process, before a standard is deployed in browsers and it becomes "too late to fix it."

Page 5: jQuery Foot-Gun Features

(builtwith.com)

Page 6: jQuery Foot-Gun Features

The jQuery Ecosystem• Code• Documentation• Developer expertise• Third-party plugins• MV* underpinning (Angular, Ember, Backbone, etc.)

Page 7: jQuery Foot-Gun Features

jQuery Evolves• jQuery 1.0 was released in 2006• Best practices in 2006 are not the same in 2014• Performance bottlenecks in 2014 also differ

Page 8: jQuery Foot-Gun Features

jQuery Evolves, You Should Too• jQuery 1.0 was released in 2006• Best practices in 2006 are not the same in 2014• Performance bottlenecks in 2014 also differ

• Web development is evolving, and that's a good thing

Page 9: jQuery Foot-Gun Features
Page 10: jQuery Foot-Gun Features
Page 11: jQuery Foot-Gun Features

Can't jQuery Just Fix It?• We fixed some of these problems in jQuery 1.9/2.0• By removing bad APIs and changing behavior

• It broke lots of code, and we knew it would• So we made the jQuery Migrate plugin

• Fixing the rest is up to you• "Please code responsibly"

Page 12: jQuery Foot-Gun Features

Foot-Gun #1: jquery-latest.js• "How can I download the latest version of jQuery?"• http://code.jquery.com/jquery-latest.js• http://code.jquery.com/jquery-latest.min.js

• "Well I always want to run the latest version!"

<script src="http://code.jquery.com/jquery-latest.js"></script>

Page 13: jQuery Foot-Gun Features

F A I L

Page 14: jQuery Foot-Gun Features

You Want the Latest? You Got It!

Page 15: jQuery Foot-Gun Features

jQuery's Hack to Save These Sites• Freeze the jQuery CDN jquery-latest files at version

1.11.1• Google CDN is freezing its /1/ "latest" version at 1.11.1

as well• So "latest" no longer means latest

Page 16: jQuery Foot-Gun Features

How To Avoid This Foot-Gun• Include a specific version of jQuery• Test the site or app with that version• Upgrade and retest when needed

Page 17: jQuery Foot-Gun Features

Features jQuery 1.9 Removed• http://jquery.com/upgrade-guide/1.9/• $.browser• Browser sniffing is a really bad idea!

• $(elements).live( … )• Handling events at the document level is slow, and doesn’t

work reliably for Apple touch events

• Use the jQuery Migrate plugin to find problems

Page 18: jQuery Foot-Gun Features

Forcing Layout

Page 19: jQuery Foot-Gun Features

All This Happens in 16 Milliseconds

From High Performance Browser Networking by Ilya Grigorik (O'Reilly)

Page 20: jQuery Foot-Gun Features

Adventures in Dirty Layout• jQuery provides custom :visible and :hidden

selectors• They let you select elements based on the display

property of the element (or its ancestors, since display is inherited)• I came across an example similar to this in an event

handler

console.time("init");$("body").removeClass("activated");$("p:visible").css("color", "blue");console.timeEnd("init");

Page 21: jQuery Foot-Gun Features

Performance

30 ms

Page 22: jQuery Foot-Gun Features

Chrome's Yellow Triangle

Page 23: jQuery Foot-Gun Features

Let's Change to Use a Class Instead

console.time("init");$("body").removeClass("activated");$("p.showing").css("color", "blue");console.timeEnd("init");

Page 24: jQuery Foot-Gun Features

Much Better!

8 ms

Page 25: jQuery Foot-Gun Features

Foot-Gun Avoidance Tactic• Probably best to avoid :visible and :hidden

altogether• But… don't use classes for strictly JavaScript-related

state• Use data- attributes or jQuery's .data() method instead• Eliminates inadvertent forced layouts or style recalculations

caused by class name changes

Page 26: jQuery Foot-Gun Features

.show() and .hide()

Page 27: jQuery Foot-Gun Features

.show() and .hide()• $("#abc").show() makes an element visible• $("#abc").hide() makes it invisible• Changes the element's style attribute to ensure it

"sticks"

What could possibly go wrong?

Page 28: jQuery Foot-Gun Features

Detached Elements?$("<span>Hi!</span>") .show() .appendTo("body");

Page 29: jQuery Foot-Gun Features

Elements Initially Hidden?<style> span { display: none; }</style>

$("<span>Hi!</span>") .show() .appendTo("body");

Page 30: jQuery Foot-Gun Features

Elements with Strange Display?<style> span { display: block; }</style>

$("<span>Hi!</span>") .show() .appendTo("body");

Page 31: jQuery Foot-Gun Features

Responsive Pages?<style> @media screen and (max-width: 700px) { #bar { display: none; } }</style>

$("#bar").show();

Page 32: jQuery Foot-Gun Features

Avoid the Hide/Show Foot-Gun• Always use classes to show or hide elements• Prevents edge cases with forcing display inline• Doesn’t get elements “stuck” in some state• Works with responsive pages

Page 33: jQuery Foot-Gun Features

Global Settings in $.ajax()

Page 34: jQuery Foot-Gun Features

What Does This Code Do?$.ajax({ url: "file.txt", success: function(data){ alert(data);  }});

Page 35: jQuery Foot-Gun Features

Ok, NOW What does it do?$.ajaxSetup({ type: "POST", dataType: "json", timeout: 500 // ms!});

Page 36: jQuery Foot-Gun Features

Global Settings BAD• Impossible to tell at the call point what the code really

does• Difficult for modular code (plugins) to work

consistently• So don't use $.ajaxSetup()

Page 37: jQuery Foot-Gun Features

Avoiding Ajax Annihilationfunction remoteCommand(options){ return $.ajax(   $.extend({ dataType: "json",

timeout: 1000, ... }, options) );}

Page 38: jQuery Foot-Gun Features

jQuery Constructor Foot-Guns• jQuery constructor takes a lot of "things"• $(function)• $(domelement)• $([ domelement, domelement … ])• $({ name: value, … })• $("htmlelement", { attribute: value })• $("selector")• $("html")

Page 39: jQuery Foot-Gun Features

What Does This Do?$(selector).appendTo("body");

Don't be fooled by the selector variable name; it could be any of the cases shown in the previous slide.

var selector = "<script>alert(42)</script>";

Page 40: jQuery Foot-Gun Features

Lots of jQuery APIs Insert HTML• That's why you use them, it's not a jQuery bug• But it can be a foot-gun• If you want to only set literal text, use .text()

Page 41: jQuery Foot-Gun Features

Don’t Blindly Trust User/URL Data!• Data from the URL can be massaged by an attacker to

steal the user's session or data and do things on a user's behalf

Page 42: jQuery Foot-Gun Features
Page 43: jQuery Foot-Gun Features

Avoid jQuery for Simple Things$("#toggle-checkboxes").on("click", function( event ) {

$(".cb").each(function() {

$(this).prop("checked", !$(this).prop("checked"));

});

});

Page 44: jQuery Foot-Gun Features

The Better Way$("#toggle-checkboxes").on("click", function( event ) {

$(".cb").each(function() {

this.checked = !this.checked;

});

});

Page 45: jQuery Foot-Gun Features

Instead of $(this)  … Use this!

$(this).is(“:checked”) this.checked

$(this).prop(“checked”) this.checked

$(this).is(“:disabled”) this.disabled

$(this).attr(“id”) this.id

$(this).attr(“class”) this.className

Shorter, Faster, and Prettier, Too!

Page 46: jQuery Foot-Gun Features

jQuery Custom Selectors• Extend the standard selectors• Aren't supported by the native querySelectorAll

method• That can make complex custom selectors slower

Page 47: jQuery Foot-Gun Features

jQuery Selector Equivalents:checkbox, :radio, :text, :image, :file, :reset

input[type=X]

:button button, input[type=button]

:header h1, h2, h3, h4, h5

:first :first-child or .first()

:last :last-child or .last()

Page 48: jQuery Foot-Gun Features

Be Careful About Native Methods$("div").on("click", function( event ) {

// Throws an error in IE8 or the Android 2.x browser

this.className.add("clicked");

// Works everywhere

$(this).addClass("clicked");

// Works everywhere if you can clobber className

this.className = "clicked";

});

Page 49: jQuery Foot-Gun Features

Questions?Twitter: @davemethvinGithub: dmethvinEmail: [email protected]

Page 50: jQuery Foot-Gun Features

Powerful API$(".msg").addClass("unread");

   compared to

var unreadClass = "unread",

   msgs = document.getElementsByClassName("msg");

var cls = new RegExp("\\b"+unreadClass+"\\b");

for ( var i=0; i < msgs.length; i++ ) {

  if ( !cls.test(msgs[i]) {

     msgs[i].className += " "+unreadClass;

  }

}

Page 51: jQuery Foot-Gun Features

Dead-Simple Plugin ArchitecturejQuery.fn.makeBlue = function() {

  return this.css("color", "blue");

}

$(".da-ba-de-da-ba-di").makeBlue();


Top Related