Blog


What's Next in jQuery and JavaScript?

The guys over at Ajaxian asked me to do answer a couple questions for them (on video) so I set about forming it into a mini-presentation. I discuss a couple things:

  • What's happening in jQuery Core, jQuery UI, and the jQuery Project.
  • What upcoming browser features I'm excited about.
  • Some of what's coming in JavaScript 1.9.
  • Some things that should change about Open Web development.

Video: What's Next in jQuery and JavaScript?

View Flash Version (on Vimeo.com) - Download .mp4 (80mb, Must be Logged In to Vimeo.com)

Update: I also have a small 320x240 video: Download .mov (16mb)

Let me know if you have any follow-up questions, I'll be happy to answer them. Additionally, this is the first time recording a presentation in my new office. I'm pleased with the result (even though the quality of the camera is quite poor). It was quite easy to get set up and perform, which is exciting - I may do some more, short, presentations if there's interest.

Tags: standards, jquery, javascript, browsers

Qualified Selectors in jQuery

Shaun Inman wrote a quick post on what he's calling "CSS Qualified Selectors". The syntax that he's proposing looks something like this:

a < img

Which says "Find me all a elements that have an img element inside of them."

To those of you who are familiar with jQuery we've had a similar selector, :has(), for quite some time:

$("a:has(img)")

If you're totally bent on Shaun's syntax (don't care for :has, I would assume) here's the two-line plugin that'll give it to you in jQuery:

jQuery.parse.push(/^\s*(<)(\s*)(.*)$/);
jQuery.expr["<"] = jQuery.expr[":"].has;

Then the following will work as you would expect it to:

$("a < img")

It's really nice having an extensible selector engine at your disposal.

Tags: selectors, javascript, jquery

Summer Speaking

My summer/fall speaking schedule is starting to solidify - with some major intensity occurring around May. Let me know if you're going to be at, or around, any of these events - I'd love to meet up.

May 17-18 - BarCamp - Boston

Don't have an exact topic chosen yet, possibly something on jQuery.

May 20 - MeshU Conference - Toronto

I'll be speaking on building interactive prototype using jQuery. More details...

May 23-24 - DrupalCamp - Toronto

The exact topic isn't clear yet, but probably something having to do with jQuery and Drupal.

May 27 - Kings of Code - Netherlands

I'll be speaking on the features of modern JavaScript libraries. More details...

May 29-30 - @Media - London

I'll be speaking on the features of modern JavaScript libraries. More details...

June 5 - Boston PHP - Boston

I'll be speaking on developing applications using jQuery. More details...

June 12 - Refresh Boston - Boston

I'll be speaking on using jQuery to develop interactive prototypes.

July 22 - OSCON - Portland

I'll be doing a 3.5 hour tutorial session on the Secrets of JavaScript Libraries (covering much of the content which will be presented in my upcoming book). More details...

October - Ajax Experience - Boston

I'll be giving three sessions: two on jQuery (beginning and advanced) and one on modern JavaScript libraries.

Tags: javascript, jquery, presentations, conferences

Classy Query

Over the past two years, seeing hundreds of thousands of people use jQuery, a major point has become apparent: jQuery simply isn't able to scale to handle the development needs of most power users. It lacks the clarity and power functionality that most developers need in order build applications in a collaborative environment.

For this reason I've put a lot of work into a new library (which sits on top of jQuery), called:

Classy Query

» View Source to Classy Query

If one thing has become apparent to me it's that users enjoy working with the typical Class-style of object creation and inheritance. Because of this I've constructed the entirety of Classy Query in an classical manner (you can inherit and override any piece of functionality that you desire).

Before we go too far, let's take a look at the type of clearly-defined code that you can now write with Classy Query:

<script src="jquery.js"></script>
<script src="classy.js"></script>
<script>
jQuery.Events.addEventListener(document, "ready", function(){
  jQuery.querySelectorAll("div").forEach(function(elem){
    jQuery.DOM.append(elem, " <b>More...</b>");
  });
 
  jQuery.querySelectorAll("div b").forEach(function(elem){
    jQuery.Events.addEventListener(elem, "click", function(elem, event){
      var next = jQuery.Traversal.nextSibling(elem);
      var animation = jQuery.Effects.buildAnimation( next, {height: "toggle"});
      amimation.start();
    });
  });
});
</script>

You can even sub-class functionality, creating your own pieces of encapsulation. All of the class and inheritance functionality is taken care of by the Simple JavaScript Inheritance code released last week.

jQuery.DOM.boldWrapInner = jQuery.DOM.wrapInner.extend({
  attach: function(elem){
    this._super(elem, "<b></b>");
  }
});

jQuery.querySelectorAll("div").forEach(function(elem){
  jQuery.DOM.boldWrapInner(elem);
});

Additionally you can treat pieces of functionality as if they were attachable behaviors, like so:

jQuery.querySelectorAll("div").attach(new jQuery.DOM.boldWrapInner());

There's a number of core features encompassed in Classy Query that really help to transform the traditional jQuery experience into something much more usable.

Class creation

The full Simple JavaScript Inheritance API is included in Classy Query, allowing you to extend and create JavaScript 'classes', like so:

var Person = jQuery.Class.create({
  init: function(name){
    this.name = name;
  }
});

var ClassyDude = Person.extend({
  sipWine: function(){
    return "Has a beautiful bouquet.";
  }
});

Inheritance

It's possible to inherit from any existing piece of Classy Query functionality, supporting a true 'programming in the large' mindset. You can inherit from, or completely override, existing methods with ease (especially since they're all classes).

jQuery.Effects.collapse = jQuery.Effects.buildAnimation.extend({
  attach: function(elem){
    this._super(elem, {height: "hide", width: "hide"});
  }
});

Behaviors

Behaviors tend to encapsulate a portion of functionality which is applied against an element (such as making a table sortable or making an item draggable). Classy Query supports a technique to make this particular implementation trivial.

jQuery.querySelectorAll("div")
  .attach(new jQuery.DOM.addClassName("current"));

No more 'this'

The 'this' keyword is confusing and frequently misused. To counter this all access to elements (within functions) is done by the first argument, rather than through 'this'.

jQuery.querySelectorAll("div").forEach(function(elem){
  jQuery.DOM.addClassName(elem, "current");
});

Re-Structuring

The hierarchy of jQuery has been completely re-organized. Rather than having a single, flat, interface through which to access all methods functionality has been broken down into individual groupings of methods. These groupings tend to, also, coordinate with the jQuery Documentation for convenience.

Additionally, nearly all the method names have been re-named in order to provide a greater level of clarity to developers. Frequently it was found that the concise method names of jQuery provided too much confusion to developers just getting started with the library. The end result is a library that is easier to read and understand for developers.

The full list of categories and changed methods can be found in the following table:

jQuery Classy Query
jQuery jQuery.querySelectorAll
each forEach
prepend jQuery.DOM.prepend
append jQuery.DOM.append
before jQuery.DOM.insertBefore
after jQuery.DOM.insertAfter
wrap jQuery.DOM.wrap
wrapInner jQuery.DOM.wrapInner
wrapAll jQuery.DOM.wrapAll
clone jQuery.DOM.clone
empty jQuery.DOM.empty
remove jQuery.DOM.remove
replaceWith jQuery.DOM.replaceWith
removeAttr jQuery.DOM.removeAttribute
addClass jQuery.DOM.addClassName
hasClass jQuery.DOM.hasClassName
removeClass jQuery.DOM.removeClassName
offset jQuery.DOM.getOffset
text jQuery.DOM.getText
text jQuery.DOM.setText
html jQuery.DOM.getHTML
html jQuery.DOM.setHTML
attr jQuery.DOM.getAttribute
attr jQuery.DOM.setAttribute
val jQuery.DOM.getValue
val jQuery.DOM.setValue
height jQuery.DOM.getHeight
height jQuery.DOM.setHeight
width jQuery.DOM.getWidth
width jQuery.DOM.setWidth
css jQuery.DOM.getCSS
css jQuery.DOM.setCSS
children jQuery.Traverse.getChildElements
find jQuery.Traverse.getDescendantElements
next jQuery.Traverse.getNextSiblingElements
nextAll jQuery.Traverse.getAllNextSiblingElements
parent jQuery.Traverse.getParentElements
parents jQuery.Traverse.getAncestorElements
prev jQuery.Traverse.getPreviousSiblingElements
prevAll jQuery.Traverse.getAllPreviousSiblingElements
siblings jQuery.Traverse.getSiblingElements
filter jQuery.Traverse.filterSelector
bind jQuery.Events.addEventListener
unbind jQuery.Events.removeEventListener
trigger jQuery.Events.triggerEvent
hover jQuery.Events.hover
toggle jQuery.Events.toggle
show jQuery.Effects.show
hide jQuery.Effects.hide
toggle jQuery.Effects.toggle
animate jQuery.Effects.buildAnimation
queue jQuery.Effects.queue
dequeue jQuery.Effects.dequeue
$.ajax jQuery.Ajax.request
load jQuery.Ajax.loadAndInsert
ajaxSetup jQuery.Ajax.setup
serialize jQuery.Ajax.getSerializedString
serializeArray jQuery.Ajax.getSerializedArray

querySelector and querySelectorAll

Finally, rather than having a generic, catch-all, method as jQuery selector functionality is deferred to the new querySelector and querySelectorAll methods. These methods only support pure CSS 1-3 selectors (nothing extra) in an attempt to avoid any unpleasant situations when a browser's native querySelectorAll is implemented.

jQuery.querySelectorAll("div").forEach(function(elem){
  jQuery.Effect.hide( elem );
});

jQuery.Effect.hide( jQuery.querySelector("#item") )


» View Source to Classy Query

I hope this particular library will be of use to the general jQuery-using population. I hope we can start to have an open dialog, moving forward, getting everyone to adopt a more standard approach to JavaScript development. There's no reason why we shouldn't be using this tried-and-true approach to application development. It's worked in an untold number of existing applications, it's bound to work here as well. Enjoy.

Tags: javascript, jquery, programming

Secrets of JavaScript Libraries (SXSW)

Today, at SXSW, I hosted a panel discussion on the "Secrets of JavaScript Libraries." We set out to discuss the behind-the-scenes nitty-gritty code that powers the universal features of the most popular JavaScript libraries.

I think the presentation went quite well. I think we could've, easily, done a 2 hour talk with all the content that we had (we had to chop off, at least, two sections at the end in order to take questions). Here are the slides:


Some of the slides will be a little bit tricky considering that they rely on someone talking about them - I'll be sure to do an audio-to-slide synchronization once the presentation podcast is released.

I want to thank all the panelists for participating: Sam Stephenson, Alex Russell, Thomas Fuchs, and Andrew Dupont. Together it helped make for a stand-out panel. Here's hoping that SXSW decides to do more technical panels next year - if this panel was any indicator developers are hungry for more code talks.

Tags: sxsw, javascript, libraries, panel, dojo, jquery, prototype

State of jQuery and Drupal

Yesterday I had to opportunity to present at Drupalcon Boston 2008. It was a great experience to be able to mingle with the Drupal folks, hear their concerns, and see what kind of challenges they're facing in everyday development.

Overwhelmingly Drupal users are not of the JavaScript persuasion and jQuery was a breath of fresh air in their development cycle. Users who had, literally, no JavaScript experience were able to produce interactions with little effort - which is precisely what jQuery is designed for.

There were already two introductory jQuery presentations at the conference so I decided to present on the state of jQuery and some of the advances that we've been making (especially in the way of plugin development and jQuery UI). My presentation is as follows:

Possibly my favorite experience was seeing Dmitri Gaskin present on jQuery and JavaScript. He's a 12 year old programming prodigy - a module contributor to Durpal and a frequent presenter. I loved watching him deftly explain how JavaScript Object Prototypes work to a room of people 3x his senior.

I had the opportunity to clarify a minor point for someone asking a question during his presentation, which made for a great photo:

I think the experience is summed up nicely by a comment on the Flickr page:

The 12 year old in the front is teaching the 30 yr olds in the room how to use the programming tool created by the guy in the flannel.

I think it's such an exciting time in which there can be a 900 person conference dedicated to a single piece of open source software. Drupal is a fantastic piece of work and I'm looking forward to seeing it grow and flourish.

Tags: jquery, drupal

Interviewing for Open Source

I've had the pleasure of interviewing a number of people to work for Mozilla and plenty of developers for the jQuery core team. There's a lot that I've learned about what makes a good candidate and I'd like to point it out, as it's generally quite different from most organizations looking to hire. Also, even between the two Open Source projects, the qualifications for a good candidate shift wildly - however there's a lot that's quite similar, and should be outlined.

Education, grades in school, extracurricular activities, and age have very little bearing on what makes for a good candidate. None of those have ever been a factor in any of my choices for an interviewee.

We've had contributors to jQuery aged all the way from 15 to 65. Stuart was hired by Netscape to work on the Mozilla project straight out of high school (which was actually detailed in the documentary Code Rush). Age is rarely relevant, as long as you can produce good code and work well with your teammates.

I don't think education has ever been a deciding factor, for me, in an Interview. Due to my location (in Boston) I end up talking with lots of MIT students (both under-grad and graduate). It's almost a given that their grades are good and that they've done well in all the required classes. This means that everyone knows Scheme, Java, and some C++ - which doesn't help you tremendously when shooting for a position developing the Firefox frontend (which is JavaScript, CSS, XUL - maybe a pinch of C++ - and is generally what I interview candidates for). Because of this I tend to look for candidates who've put a lot of effort into extra research positions or side projects.

I'm always surprised by the number of irrelevant extracurricular activities that people put on their resumes - and the number of "awards" they've received. These mean virtually nothing to me. I'm glad that you competed in a virtual robot battle competition, but how does that effect your ability to create good JavaScript code? This ends up weighting very poorly against outright experience.

Conversely, experience and initiative have a huge amount of power over an applicant. If you're able to demonstrate that you've devoted large amounts of time to building side projects (especially when they're Ajax-y web applications - PHP, Ruby, Python, Perl - all good). Since most of the people that I talk to for Mozilla are coming from MIT they all end up being amazingly similar. The deciding factors for a candidate come down to how they've gone beyond the basic program and excelled. This is especially important since good web development skills aren't seemingly taught in the MIT curriculum, which is a shame.

Location and native language can matter, depending on the project. Mozilla, for example, is a highly distributed organization, however some teams (like the platform team) tend to work mostly in Mountain View, CA. Additionally, due to frequent meetings and communication, being able to speak and understand English is incredibly helpful. On the other hand, for jQuery, location is not a factor at all. The jQuery team has only met once (and there's some team members whom I still haven't met). Much like Mozilla, we're distributed across the globe - Germany, Florida, China, California, Romania, Colorado, Australia, and on, but we don't have a central base. Being able to speak English is much less of a concern for us - we're more open to letting your code speak for itself.


Manning the booth at a recent MIT Career Fair.

Since I end up looking at, primarily, most candidate's JavaScript skills I tend to break down the topic into a couple areas:

JavaScript Language: Good knowledge of the language - an understanding of its functional aspects and prototypal inheritance are usually the most that I can hope for.

Cross-Browser Code: Writing effective cross-browser code is incredibly difficult and can be a good way of marking a proficient JavaScript developer. One of my favorite questions to figure this out is "What is your favorite cross-browser bug?" - either the candidate has like 20 answers or doesn't know what I'm talking about.

Testing: Having test-backed code is pretty common in software development but still in its relative infancy in the land of JavaScript. Developing JavaScript tests, using a test suite - or even having written your own suite - score big.

For Firefox Frontend Engineers, in particular, I also tend to look at the two other core aspects: CSS and XUL.

CSS: It's surprisingly easy to weed out people who do, or don't, know CSS. Ask the question "What's the syntax for making all paragraphs on a page red." If they aren't able to give you some combination of "p color colon red" then it's time to move on. If they handle that then it's good to explore CSS property manipulation in JavaScript, making sure they have a good grasp of that.

XUL: By far the most challenging skillset to find. Oftentimes when I actually interview a candidate that has XUL knowledge they're more proficient than I am. However, most people aren't familiar with XUL so I tend to explore topics like XML, XPath, XSLT, and SVG. Having good knowledge of any of those is a big win.

If nothing else it should be noted that I care a lot about hands-on experience, especially when it comes to JavaScript and web-related technologies. Showing that you've proven yourself through hard work is immensely more valuable than having gotten good grades in some un-related programming class. I tend to think that this emphasis on producing real results is sort of the cornerstone of Open Source development and is one reason why I am especially happy to be completely immersed in it.


By the way, at Mozilla, we're always looking for awesome developers. If you're a top-notch web developer, maybe you should consider taking the leap into Firefox development. The territory is completely familiar (JavaScript, CSS, XML) but the output is absolutely different: An application used by over 150 million people. Tell them I sent you and I'll put in a good word for you.

Tags: jquery, javascript, jobs, mozilla

Selectors that People Actually Use

This post has been a long time coming. It's a combination of my distrust for JavaScript CSS selector performance analysis and my disdain for the CSS 3 Selector specification.

To start, I want to give a little bit of history regarding jQuery's selector engine. When I first started working on its implementation it was mid-2005. It was mostly done as a personal challenge to myself - implementing a specification for kicks. You can see some of my early thoughts in a post that I wrote on Selectors in JavaScript. I completed my implementation on the same day as the first, other, JavaScript CSS selector engine: cssQuery. I then held of and merged it with some of my other efforts, which eventually resulted in jQuery. When I first implemented the engine, I went for full CSS 3 compliance (mashing in XPath-capable queries, as well).

Fast-forward 7 months and jQuery is starting to get a capable community. In preparation for jQuery 1.0 I decide to analyze the features of the engine to see what people are actually using. I ran a poll (which, unfortunately, has been lost) in which I asked the users which selectors they used. As it turned out there were a great number that no-one had any use for, whatsoever (and, in fact, this remains true to this day). At this point I removed them from the engine, breaking compliance with the CSS 3 Selector spec. Here's some of the selectors that were removed:

  • E:root - Rarely used in HTML. You already know what the root node is - it's named 'html'.
  • E:empty - This might be useful if it could include empty whitespace text nodes, but it doesn't. This will only match elements like <img/> and <hr/>, for whatever use that is.
  • E:lang(fr) - This could be achieved in so many other ways - but in the end, how many multi-language-on-the-same-page sites are there?
  • E:nth-of-type(n) - I'm not sure what the motivation was for creating all the -of-type methods, I'm sure it sounded great on paper, but in the world of HTML it's not very useful.
  • E:nth-last-child(n) - Another "great on paper" method. Don't think I've ever seen it used.
  • E:nth-last-of-type(n)
  • E:first-of-type
  • E:last-of-type
  • E:only-of-type
  • E:only-child - When does this occur? and why would you need to select it?
  • E ~ F - Only selects adjacent elements, in one direction. Why a ~? Why only one direction?
  • E + F - Only the next element - rarely useful.
  • E[foo~="bar"] - Only matches values in a space-separated list. This is only useful for classes (which is taken care of with .class) and the ref attribute. Why not just use *=?
  • E[hreflang|="en"] - Another selector that is really only useful for a single attribute - and not a popular one, at that.

What's fascinating is that no one has ever, ever, requested that these features be added back in. They have virtually zero real-world use and applicability. In fact, with the exception of "E + F" all of these selectors were added, exclusively, in the CSS 3 specification. I'm not completely sure what the thought process was in selecting them, but it's pretty obvious that it wasn't grounded in application, but in theory (which isn't really the spec-writers fault, considering that there were very few CSS 2-compatible implementations at the time).

Only later, after performance test suites started to arrive, did people start to care about the existence of - and the performance of - these selectors (and hence why selectors like +, ~, and [foo~=bar] now exist in jQuery).

To compensate for the shoddy offering of current CSS selectors, JavaScript libraries have had to write whole supersets of selector functionality to compensate for missing features. For example, jQuery includes both new selectors (such as ":hidden" and ":has()") and new selector methods (like ".parent()" and ".prev()") - all of which provide the user which phenomenally more functionality and clarity than the what is in CSS 3.

Now, I'm sure I'll probably get lots of feedback saying "but 'E + F' can be useful, look at this example" or "of course ~= is useful, you can use it on rel attributes" - that's not the point. The fact is that they are woefully un-used. To the point that they are a burden upon the implementors of the specification. What's the point of implementing the above features - or more importantly: optimizing the above features for speed - if no one is using them.

Which leads me to my next bone to pick:

Performance isn't Compliance

Everyone and their brother seems to use the SlickSpeed selector speed test suite. That's fine, as far as implementation goes it's a pretty good take on the matter. It runs quickly, spits out pretty results - users love it. However, it's doing two things - and that's one thing too many: It's testing for both performance AND compliance of the selector engines. For example, if a user were to run the tests and see poor performance for, oh say, :nth-child(2n+1), they would be shocked, nay, appalled at the overall performance of that selector engine. But here's the rub: That's from a selector that is virtually un-used. (:nth-child is occasionally useful, in and of itself, but the An+B syntax is virtually worthless). But this is a point on which SlickSpeed does not care - since it's also testing for compliance, in addition to performance, all tests are treated equally and "without bias."

However, that's precisely what isn't needed: Selectors require bias. I've often argued that the speed of an ID selector is far more important than the speed of an attribute selector (for example) because of how commonly it's used. However, up until this point I've never had data to back up this claim. I have resolved that.

I present to you the most commonly used CSS selectors used by jQuery from 59 of the most popular jQuery-using sites (which was borrowed from the featured sites list). (Fun fact: The use of $(DOMElement) was more popular than all other selectors combined.) Here's a small selection of the selectors found:

Selector % Used # of Uses
#id 51.290% 1431
.class 13.082% 365
tag 6.416% 179
tag.class 3.978% 111
#id tag 2.151% 60
tag#id 1.935% 54
#id:visible 1.577% 44
#id .class 1.434% 40
.class .class 1.183% 33
* 0.968% 27
#id tag.class 0.932% 26
#id:hidden 0.789% 22
tag[name=value] 0.645% 18
.class tag 0.573% 16
[name=value] 0.538% 15
tag tag 0.502% 14
#id #id 0.430% 12
#id tag tag 0.358% 10

View the rest of the selectors with a full explanation...

I spidered the JavaScript of all the sites, parsed through them, and found the appropriate selectors to compile the list. Here's some things that I learned from the data:

There doesn't seem to be a correlation between performance and selector use. For example, ".class" is far more popular than "tag.class" even though the second one is much more performant. What's especially important about this is that the degree of performance hit isn't that much of an issue. For example, the difference between 4ms and 30ms is virtually imperceptible. Instead there is an overwhelming trend towards simpler selectors. Obviously, user education could help, but it's unclear as to how much that will change things in the end.

A couple of jQuery's custom selectors are immensely popular: :visible, :hidden, and :selected. However it is unclear as to how useful they would be outside of a JavaScript-based CSS selector engine (there's no real point in styling a hidden element).

A bunch of jQuery's convenience selectors: :checkbox, :radio, :input, etc. would be quite useful, within a CSS selector spec - and it's good to see them in wide use here.

There's a bunch of unexpected queries that are used: "*", ".class .class", "[name=value]", and "#id #id". These types of queries are grossly under-represented in current performance test suites.

...there's one thing that needs to be taken from all of this data, though: Speed test suites need to test reality rather than specification.

I'm perfectly ok with having two completely separate suites, one focusing on speed and one focusing on compliance, however mixing them does no one any favors: Users get a confused perception and suite authors (and browser vendors!) waste time dealing with optimizing things that don't matter.

My proposal: A standardized performance suite (based on SlickSpeed, is fine) but populating the tests with comparable selectors to the ones shown above and weighted based upon their relevance. Thus, the speed of the #id selector should, actually, consume 51.29% of the total final score. This means that being 3x faster at this test would actually be 102x more important than becoming 3x faster at "tag tag". This is absolutely not represented in any, current, test suites and needs to be rectified. Of course, I'll be happy to seed my selector list with results from other popular sites of other selector libraries.

I'll be fine constructing this suite, as well - I just want to make sure that there's enough interest. I think this proposal has a lot of merit and should be strongly considered - the result will be a selector performance suite which will benefit everyone.

Tags: jquery, javascript, performance, css

· « Previous entries

Current Projects

jQuery JavaScript Library

jQuery

Comprehensive DOM, Event, Animation, and Ajax JavaScript Library.

Recent Projects

Pro JavaScript Techniques

JavaScript Book

The best techniques for professional JavaScript. Published by Apress.