Best Practices in Javascript Library Design


Uploaded by GoogleTechTalks on 08.10.2007

Transcript:
>> Good afternoon. Welcome to Building a JavaScript Library. We're very happy to have John Resig
here with us today. John is a JavaScript evangelist, and he works for Mozilla Corporation and he's
the author of the book "Pro JavaScript Techniques." He's also the creator and lead developer of
the jQuery JavaScript Library and he is the co-designer of the FUEL JavaScript Library
which we included in the Firefox3--is included in the Firefox3. And he's currently located
in Cambridge, Massachusetts. So thank you all for coming today and here's John.
>> RESIG: I want to thank everyone for coming out today. I really appreciate it. So just
a little background on myself. I am the lead developer of jQuery, I work for Mozilla. So
I do--I still do jQuery in the evenings, so to speak. And at Mozilla, I'm--right now,
now I'm promoting JavaScript 2. I'm really excited about that. But today, I'm here to
talk about specifically the two libraries that I have experience in building and maintaining,
and how to--how to apply what I learned into building your own JavaScript library. So,
the first library that became something that I built was called jQuery. Released this early
last year and it's explicitly focused on DOM Traversal. The DOM Traversal was the absolute
core of the library. And then there was a bunch of extra things to learn, so advanced
in AJAX, animations. And the primary focus of the library was in having--being able to
write really succinct code while--and having a small file size while still being extensible
via plug-in architecture. If you've never seen jQuery Script, this is some brief example.
jQuery is focused on--it can break it down into two parts. The first part is where you
find something, the second part is where you where you perform an action against it. And
so in jQuery, you're always finding something. I use CSS selectors, and it finds a set of
elements, and then you perform an action against them. So, in the one there, you find all divs
that are inside the element that has an ID of main, and you're adding a class to them,
or you perform an animation or binding in an event or loading a document in through
AJAX. And personally, I'd like to think that we've--that I did something decent with jQuery.
Currently, we have about 25 people working on jQuery in all various aspects of it. I
get about a quarter visitors per month and this is on Google trends here. You can--you
can probably guess which one is jQuery. And these are the other popular JavaScript libraries
like Prototype and Dojo. So I think--I think we're doing pretty well for ourselves at the
moment. The other library that I have experience with is called FUEL. This going to be in Firefox3,
and it's designed for extension developers. Currently, you can use JavaScript to develop
an extension, interacting with something called XPCOM. And I don't know if you've--who here
has had experienced writing an extension. It isn't the most fun thing in the world and
it could be a lot better. So FUEL is designed for that. It's designed to help web developers
get into writing extensions. So there's all sorts of helpers for bookmarks, events, preferences.
It's written in pure JavaScript and it's designed to be extensible. So here's some quick examples.
So here, we're going through all the preferences and finding all the preferences that are--that
have been modified by the user, looking for when the application--when--looking for when
Firefox is quitting, when the user is quitting Firefox, opening a new tab and activating
it, and then removing all Google bookmarks from your--from your bookmark cache. So I
generally distill JavaScript library authoring into these topics. And I'll--and I frantically
try to cover them all today. So all the way from your initial design of when you're designing
the API that you want to implement all the way down to maintaining the code that you've
written, so there's a lot here. The first part of writing a solid API is--that I find
to be incredibly important is that your code should be orthogonal. And what I mean by that
is that whenever you perform an action on an object, it should always be performed everywhere.
And I like to use the analogy of, you know, the--of CRUD in that in CRUD you can, you
know--you know, add, remove, modify, delete and so I like to use that when designing a
new API. So, in FUEL, every single object has the same methods and properties. So, for
every object, so for all bookmarks--to get all bookmarks, you do "bookmarks.all." To
get all preferences, it's "preferences.all." In order to get--to add a new preference,
it's "prefs.add" or "bookmarks.add." It's the same thing for every single API and using
the same method names and the same conventions. So, that way, if you know how to do preferences,
for example, and you want to do bookmarks, there's no learning curve because--since you
already know it's the same. And what I think is critically important is that, for example,
in jQuery, when I first implemented it, I forgot to add a remove attribute function
and it was missing literally for months. And in some of you guys, it wasn't as popular
as adding an attribute value. But if I think in time when I first started to map out, okay,
if I'm adding an attribute, somewhere, I should be, you know, removing it as well, then I
probably would have caught that. Granted, it's in now, so that's not really an issue.
So, specifically with FUEL, I made a grid, such that you would have literally the columns
were add, remove, modify, delete or--sorry, add, remove, modify and, you know, the rows
were each piece of functionality so, you know, a preference or whatever. And then--and I
could literally just fill in the blanks and say, "Okay, have we--have we figured this
one out yet? Have we done this one?" And make sure that we have complete average of the
API. Another point when writing an API is that you should fear adding new items into
your API. You need to keep it as small as possible because every single method that
you add, you're going to have to support. So that means, you know, that somewhat indefinitely,
if you--if you add in a single a method, you need to be able to sort of pre-cognitively,
you know, anticipate what users are going to be doing with that. So I think wherever
possible, if you can get away with not adding in a method, you should. So, in jQuery, at
one point, I added in some methods for CSS helpers, so like ".top, .left, .background."
And they weren't used a whole lot but they provided an extra--I--like I said, it would
be below on top of the API since there was already a CSS method from manipulating CSS
properties. So, I added them in and then people were using them and we had to support them.
And then when it came--you know, when I decided that it--these weren't necessary and remove--and
decided to remove them, it was--it was a hassle. So, I consider that you should just seriously
think about anything that goes in. And now I'm very, very stingy whenever anything goes
into jQuery. You should embrace removing code wherever possible if there's--if there's--and
again, going back to supporting--because if you're writing a library, you have to support
everything that's in it so you should, wherever possible, remove code that could be handled
elsewhere. By reducing the size of your API, you make it easier to learn, you decrease
your file size which is especially important in JavaScript and it makes--it generally makes
your code more maintainable. There's less code there, it's going to be easier to maintain.
So, a long time ago in jQuery, I had implemented a full CSS 3 selector syntax. And there's
a--I don't know if any of you have ever used CSS 3 selectors. It's a really stupid specification
and, yes, there's a lot of really bad stuff in there. For example, you can select all
children but you can't select your parent. You can select an adjacent sibling, next to
adjacent sibling but you can't eject a previous adjacent sibling. It's just like really like
they--so they did not think orthogonal. They were like, "Oh, let's just select next and
let's--who cares about previous?" And it's really frustrating to deal with. So, I actually
ran a poll where I had people check off each selector item that they actually have used
and then at the end, there was a whole bunch that nobody checked. And there was one that
was like nth of type. I don't know if anyone's ever heard that one but it selects the nth
child of a specific type. And some people had checked that and we found out they could
actually just use nth child, so we were able to remove a large chunk on the CSS3 specification
which is good and bad in that we're no longer completely compliant but at the same time,
no one was using them to begin with. So we reduced our total API and made things easier
to maintain. And so in 1.1, additionally, this is separate. In jQuery 1.1, we reduced
the size of the API by 47% just removing methods and stuff that didn't need to be there.
>> In the metrics, there is [INDISTINCT] size. >> RESIG: So, the metric here was each API
item, we had to document. So if we had to document something, so we move 44--47% of
what we had to document as well which is great because that means we have to write less.
Yes. >> We always want to remove like replicating
methods and stuff like that, but how do you that without breaking people's websites? Like
with a [INDISTINCT] because [INDISTINCT] >> RESIG: All right. So how do you not break?
I think--okay, provide an upgrade path. The important point is that you can just willy
nilly remove stuff; otherwise, it's not feasible. So, there's two ways to do it and with jQuery,
what we do is if we change the API, so like from 1.0 to 1.1, we change the API and provided
a plug in on top 1.1 that gave 1.0 users an API that felt like 1.0. Another way to do
it is to give 1.0 users an API that feels like the 1.1 API. So, I mean, you can point,
decide which direction you want to point. Personally, I think pointing backwards is
easier since generally, the more modern API, you don't want to be duplicating functionality.
And so the--by providing a plug in, so they would just use the new API then direct it
beneath to include a backwards compatibility API and all the old plug-ins and all the old
code would just work. It nothing--like nothing had changed at all.
>> On that note, to do that though, you'd have [INDISTINCT] problem. An advanced API
[INDISTINCT] >> RESIG: Yeah.
>> You'd probably identify the orders between [INDISTINCT].
>> RESIG: Yes, so the question was, you know, did you identify your versus cleanly? And
you know, obviously, and map does Maps with the identifying versions. So, yeah, it's pretty
important that you do cleanly identify it so that you just know at which point they're
upgrading from or to. >> All of these here [INDISTINCT] we need
to have a version two but that would--that changes every two weeks. So, can we change
something that's in version two... >> RESIG: Yeah.
>> ...which is currently 2.86? Then we will break anyone who [INDISTINCT]
>> [INDISTINCT] >> RESIG: Yeah.
>> Right. We could--I mean, that's when we made a big jump from one to two. That's [INDISTINCT]
to do anything, but it's always a concern for us when we get anything from three to
two. >> RESIG: Yeah, so the--that's actually a
good point because--so it--the question was over, you know, that the version two, the--this--the
minor releases of version two keep breaking things. So, it--that's something we tried
to stop in jQuery a while ago in that anything--so 1.1 may break something while 1.1.1 won't
break anything. I mean, obviously, that's--I don't--I'm not sure what kind of issue that
is other than to say that maybe whatever file that users directly hotlink to should be something
that's not API changing but give them an option to link to the bleeding edge. You know, so
differentiate between a stable versus a bleeding edge. With API, you should always--and this
goes back again to simplifying your API. Reduce your API to its most common root. And then
when--because when you do that, you can have a core function that you can build on top
of. So, right now in jQuery 1.2, I'm actually removing these three methods here and--so
that you can get, for example, the first element, the first three element--or sorry--everything
after the first three elements and everything before the first two. I--and these were kind
of--they're kind of kludgy. And when I was looking at this, I realized that there's already
an awesome method for this and--whose usage is already known called Slice. The jQuery--I
don't know if you're not familiar with it, the jQuery object, it behaves like an array
and so, by implementing a slice method, you now have a huge amount of power being able
to do things that you couldn't even do with this and we reduced our API by 67%. Consistency,
you--when writing your API, you should be consistent everywhere. Obviously this is easiest
if you're--if it's one person writing the API. If it's not, you should write up your
guidelines a head of time, so that everyone knows what is expected. And I become consistency
in the three areas. The most obvious is naming. If you're going to pick a naming convention,
you know, if you're using camel case or not or, you know, if you--like for events, if
you want to do dot on click versus dot click, so in jQuery we do dot click for no particular
reason other than that's the convention that we adopted. So, by doing that, that is what
users should expect going forward. Argument position, so when someone calls--when your
methods, they should know, in which order to expect to build a passing send. So specifically,
being in passing in options object, so, just in JavaScript, just a native object that has
key value pairs, well you know, properties and values. In jQuery, we always pass it in
first, always, everywhere in the API and if we ever have call back function, that's always
the last item in the method. So by having that at least a little bit convention, users
can expect that if they want to have a call back to something it's always going to be
the last item and they can expect that. And within a call back, you should always make
sure that the context is the same everywhere, so--because if the context is constantly changing,
sometimes if it's an object, sometimes if it's an element, no one knows how to interact
with it. So, jQuery, the context is always refer to the DOME element with each--that
is reference to. So implementation, so this is the--what I say the progress--the evolution
of a JavaScript coder. So, when--so it goes something like, when someone is just starting
out they--at least a program are coming in the JavaScript. It's something like, "Oh man,
everything is a reference." This is great, you know, it's object's, I can understand
this, you know, I understand how this works. And then--then they realize they can do object
or enter code. And, you know, this is sort of quickie, we can't understand their adrenalin.
I've done some of the clicks, how to do object prototypes. And then, you know, there's--you
can see this, you can usually tell how someone's advance to JavaScript. Where they hit some
point like, "Prototypes, I understand." And then they try and--they do everything with
object prototypes. And then I think the final progression of a JavaScript coder is when
they realize that although there's subs good, but it's all about closures. And that there's,
you know, their code just suddenly becomes this giant closure mind field of different
scopes and context and--so there's a couple quality coders who I really inspire, who have,
you know, fantastic user closures in their code and it's just really a thing of beauty.
>> [INDISTINCT] >> RESIG: I--well, it's teaching them this
first, that would probably break their soul. But I do because their functional programming
to be an absolutely imperative concepts. And that--yeah, and is it--but the--yeah, I'm
saving that one. All right, so the--so first specifically for functional programming, that
understanding closures, you know, not only does it make you a better programmer, it is
specially makes you a better JavaScript programmer. And, so, this SnipIT here, having an anonymous
function wrap and executed is one of the most powerful constructs that you can use in JavaScript.
It gives you just an anonymous sculpt that you can interact in and you can define local,
local variables within this scope that is in accessible outside. And you'll see this
used again and again in code and in different variations, but it's really important and
then it can--and it sort of, transfers down to other concepts, so like being able to write
such a macros of to some degree. So having--you're generating custom functions on the fly. So
here we are generating three new jQuery methods dynamically that encapsulate another piece
of functionality and this is all using closures because this name here is within this scope.
Here's another SnipIT, I'd like this one a lot. It's just--it's similar to the last one,
with this difference. So you can call functions in JavaScript within a different context and
what happens is, is that whenever you call an anonymous function in JavaScript, it's
default context is the window object, the global object which doesn't really help you.
So if you call it with the call method and you said it's context to this, you now have
the context that is equal to the current scope and you can have local variables. So I consider
this to be deceptively powerful and until--at least until JavaScript 2 comes along. At least
now with the JavaScript 1.7, you can have all the "what statements" and you can have
locally defined variables. I think this is new little self that will hold you over.
>> [INDISTINCT] >> RESIG: Say again?
>> [INDISTINCT] >> RESIG: Yeah. Because it's...
>> [INDISTINCT] >> RESIG: You mean--meaning to like a block?
>> Yeah. >> RESIG: Yeah. You see--you can--exactly
we can do. So in JavaScript 1.7 is there--so there's a normal, you know, statement and
then you can also do--let then it will be within this block. So, within this, within
this block here. This variable will be equal to 100 as supposed to this one which will
be equal to within the whole block. Encapsulation, this is a really important point for developing
reusable and embeddable Java--you know, the JavaScript libraries. So if you want to--want
your library to be able to live with other libraries in other random pieces of code,
you really need to this because you don't want your code escaping and potentially harming
other people's code. So, are we getting more in this second, but you, you just want to
make sure that nothing of your--there's no variables that you define weak out and affect
how other people write since the JavaScript you really can, you can just blow away anyone
else's code. And, so the nice part of this is that--so if you wrap--this comes up again,
it comes up again, you wrap your entire library in it and then you define variables within
that scope. Compressors can make optimization so, for example Dojo's compressor it looks
at variables within a scope that don't escape that scope and they can do rewriting of them,
so that the variable will then can change from, you know, my long variable name into,
you know "A" and then--so within that scope you can use optimized variable name that compresses
really, really nicely into, you know, a minified code. Name spacing, this--name spacing has
a potential to become very verbose and it's really easy to get lost. Some libraries do
this better than others and but the goal of name spacing is that you want to use as few
global variables as possible, the less global variables that you use and the less that you
modify global objects, the better because your code will just be a better citizen of
the page that you are currently in. Right now, there's a couple of libraries that do
one name space really well. Dojo, Yahoo, UI, jQuery. MochiKit is a little--they seem that
they have one global name space but they automatically introduce everything into the global names
space and then they have to like retract it again. It's a little bit weird, but Dojo and
jQuery at least do pretty cleanly. And, there are some questions that I would like to ask
and that it says, "Can my code coexist with other random code on the site?" This is usually
the easiest one to obtain and that you want to make sure that none of your code blows
away anyone else's code or affects anyone else's code. And you also want to make sure
that no one else's random code, no matter how badly it's written, will affect your code.
So, if they extend the object prototype you need this to work. I mean--and you can tell
people not to do it but it's going to happen and you just need to--you need to be safe.
There was a--these are some questions now that I'm starting to look at, because I think
they're practically interesting so, "Can my code coexist with other copies of my own library?"
So, if you include jQuery and then you include your jQuery 1.1, you include jQuery 1.2, can
you use them together on the same page? Will they blow--will they over write each other's
methods? That's a harder problem to tackle it's--it's definitely feasible and so that's
what I'm looking at I want that get that in for jQuery 1.2. The other question is, "Can
my code be embedded inside another namespace?" So, for example could--could I take the jQuery
namespace and copy into let's say Dojo namespace, so I can do now "Dojo.jQuery" and no library
can handle that. Because--you--you they depend on special context is being set and special--you
know naming being available, it's--it's also hard problem and again a little this performed
but you should never extend native objects ever, and this is--it's almost a philosophical
point right now that--you know the prototype library. It's a fantastic library, absolutely
fantastic, the developers have really stand up and they--they enjoy extending native objects.
That's just how--how they role. So, but I--I don't like it that it's--you know they used
to have auto prototype, they removed that pretty early and that extending all objects
in the JavaScript, is incredibly dangerous and that you can--you can no longer iterate
through an objects keys without getting these random other chunks to code in. They're--they're
hitting problems now, but I think it's absolutely imperative that in the JavaScript library,
it should first work across browser, first. Second, it should have functionality, meaning
that if your library did nothing but find elements by class name, but it worked in every
browser, that would be a perfect library and that it--it achieves the goal perfectly for
all people. But, if you can never--if there's some piece of function that you've implemented,
where you just like it doesn't work in Safari, sorry. You know I don't think it's valid to
claim that, that is a valid piece of functionality of your library if you just, you know, if--if
it's not supportive in that case so prototype they extend native HTML elements, so extend
the HTML element prototype to add additional methods on. That doesn't work in internet
explorer, so they have this crazy shenanigans that you have to, you know, you have to perform
in order to--you have to like double wrap your objects in order to traverse around and
it's very inelegant, and I don't think that's a valid solution because it's just...
>> [INDISTINCT] >> RESIG:...and additionally, another issue
that's coming up now, is in adding methods to global objects. So, specifically, the new--there's
a new get element by class name, that's from HTML 5 and we implemented it in Firefox 3.
So, the--we Mozilla in Firefox 3 and the problem is that prototype also implements that method
and so, at first they were blowing away the data method which is like a hundred times
faster, you know, just completely blows them away. So, what they did--what they didn't
started to do was they checked to see if the method existed or not and if it did, and if
they all existed they didn't touch it, which is good. But, the problem was, is that people
didn't wrote code that relied on the return value of what prototype did. So, prototype
returned a modified object that you could call a DOT each method on, and because that
DOT each method no longer works it was breaking code again. It--it's a crazy world and this
is why I don't like extend--extending native objects at all because you just have the potential
for this--this weird mishaps to occur that you don't expect and at the same time, you
know, I think another--and another one was that--I think I've used to implement array.forEach
and so when it came and--and there native forEach in Firefox 2, and the data forEach
is very fast, it's lightning fast. But the thing is that if--if you wanted to take advantage
of that and someone else already had included prototype in the page you would end up using
prototypes one because it existed which is so slow. You don't want to use that slow one
because you can do better. So, it--again it--it doesn't just fall back to piece--missing pieces
of functionality and also fall back to speed issues. So, perform type checking, I say--I
say this one but I--I do it very sparingly in jQuery a little bit more so in Fuel. Well,
in Fuel, you have a--everything's implemented to an IDL interface and I don't know if anyone
has had to do IDL or I specifically, IDL with java script. It is horrible because you essentially
you can only have specific types come in and then you essentially lose all the beautiful,
you know, variable length arguments that you've come to love in java scripts. So any way,
by having type checking, you can make you API very fault resistant. So if--if a user
sends in a null or an undefined by accident, you can handle that gracefully and hopefully
give them an air message that at least point them in the right direction. In other case,
is where a user passes in something that they expect to work, for example; passing in a
number into the CSS function so [INDISTINCT] setting a [INDISTINCT] or the height to a
number. Browsers behave a little differently with that, so you can turn that into a string,
you know and not a pixel value. Now, the point at which I sometimes disagree with other people
is around air messages. They are obviously, immensely useful for people to debug with
but they're also very byte-costly, you know they are--you can be transferring many, many
[INDISTINCT] of just air messages down the pipe and I think the bet, sort of functionality
is better left to a debugging extension. So providing your library and you can throw in
a debugging extension and so you get all this wonderful air messages.
>> Is it possible that the [INDISTINCT] filing [INDISTINCT] recognition [INDISTINCT]
>> RESIG: Exactly. Oh, so the question was why--why not just pull the air messages in
with the HTML [INDISTINCT] request? That's valid too. I mean, I definitely consider that
to be an option that you would turn on when you're in a debugging mode or something.
>> That's true, even I [INDISTINCT] >> RESIG: Yeah, yeah so there's no--I don't
really consider be any reason to pass long air messages. Another tip that I like, so
tweaking your object constructor, I use this one in jQuery so jQuery is--is an object and
you can instantiate it. But if you throw this here on the top, so windows is a global object
and you try to see if the context is equal to the global object. If that is the case,
when you call jQuery like this, so what it does now is that, instead of just try to run
jQuery like a normal function, it goes back and instantiates it self and returns that
result. So now--so now this statement in jQuery becomes equivalent to instantiating it and
that it--its makes for a shorter code, you know, users don't have to worry about that.
Well, as a developer, you still get all the benefits of having this--this fast instantiation.
Another quick tip for air messages, you should never gobble air messages. So if a user causes
an air to occur in their code, especially in a--in a call back, so an Ajax call back
or, you know, a loop and a function in a loop, never gobble users air messages. It seems
really tempting and that you don't want there to be bad things happening on the page or
whatever but you just ignore that and be able to let things pass through. And I consider--I
think you should even do this with your code, with the library code and that if an error
occurs in the library, don't--don't consume it, you just let it go free, unless you're
including air messages or [INDISTINCT] some sort, you just have to let it pass through
and at least give people the hope of debugging your code. So, complex applications, I consider--there's
[INDISTINCT] be a couple of solutions to complex applications. The most important of which
is extensibility and I think that if you want to write good code. You should keep a light
core of functionality and allow users to add in additional pieces of functionality easily.
And we do that in--just about every aspect to jQuery because jQuery is well we just keep
it small and light and let other people add in what they want and if they want a crazy
bouncing animation with some accordion widget, you know, that's fine, they can include that,
but we won't include that natively. So, just an example, here's three different ways to
extend jQuery. The top one is the most common one, this is a typical jQuery plug in, you're
adding a new method into the jQuery object, your own function and you can--now users can
use it like any other jQuery method. You can add in customs selectors so you just can now
use your own custom selector and you can add it your own easing animations, so if you want
to have a bounce--a bounce animation, you can do that. And other really important side
effect to this is that it fosters a community so the--users, you know, can release their
own code and get recognition for it, you know that's fantastic. You know, you saw a lot
of that happen in the pro community in around C-pan, being able to release code and maintain
it. So, we're doing that now in [INDISTINCT], we have a couple of hundred plug-ins, of users
just contributing out. So, a lot of people consider, object-oriented code to be the solution
for writing complex applications. I get this time and time again, people will look at jQuery,
coming from a--typically the Java world, and they're looking like, "Oh, what's this?" It
is like a one liner and, you know, why not have an object, you know, to use that here.
And I think you know object-oriented code is an answer, I don't think it's the answer,
especially within the world of Java script, because you have such powerful constructs,
you know functional language, constructs, that, tis'--I don't deserve to be a perfect
solution but any stretch, at least not until Java script 2, when there's packages and classes
and all sorts of nice things. What I consider to be a better solution, is the use of first
plug-ins, but second--secondary having custom events, massage passing, so, between one object
to another is absolutely fundamental to having a library that is usable in a complex situation.
And I can't really stress that enough, other than to say that, that all these libraries
now use--Dojo was a pretty big pioneer in this, and that all their library and all the
things that snap into their library, use custom events to communicate, it's pretty elegant,
jQuery we use this and we're--we've had custom events for a long time but we're getting understanding
them and how to apply them, yahoo UI has--in prototype just added them, the new 1.6 release.
And so this way, you can now, for example your component can listen for a drag event,
something that normally--doesn't normally exist and you can now trigger a refresh event
on a table or something. So, dealing with browser bugs, so quirksmode--quirksmode are
the, the quirksmode are the website, run by PBK came, fantastic resource, I mean they
helped so much back in the, you know, the--when I was first learning Java script. But the
fundamental problem with it, is that it explains where a problem exists, a specific browser
bug exists. So it will say that the offset top method doesn't like quite work, quite
properly in this browser, and that's good to know. But it doesn't tell you how to solve
a general purpose problem. For example, how do you get the computed style of an element
in a cross browser manner, it doesn't explain that. It explains a particular method of an
API and I--what I think is much more interesting and much harder, is understanding these Meta
problems, these things that encompass multiple API's. So specifically, looking at, how to
solve a whole problem set, there's a couple of problem sets that are already solved, what
I consider to be solved, and that is in aerial DOM events and DOM Traversal. Those are pretty
well thought out and you can find a lot of good documentation on that, but there's a
lot of them that still require just a tremendous amount of hard work, so the problem of getting
an attribute value out of an element, that ones being--very close to being solved, I
think the prototype guys are making good progress, we're making some good progress right now,
and the one that, I haven't seen tackle yet, but we're starting to now is getting a computed
style, so hear me out what, how an element currently walks, and it is a fantastically
hard problem because no browser has even attempted to standardize on anything, except there is
nothing to standardize on and so what I've done in these cases is to, in your test week,
[INDISTINCT] just hundreds of possible values so it has against some type of [INDISTINCT]
getting a computer style, and looking at a dozen different types of elements. Are they
displaying on, are they visible, you know, are they a block within another hidden element.
Are they normally, supposed to be in line it's just--in using so--using that sort of
values and then comparing the color attribute the background color the, you know, the height,
the width and in ends--and you permute all this out, you have such a couple hundred test
cases to work with. >> Do you expect that if you [INDISTINCT]?
>> RESIG: So do you expect that if you had to work in presence window size changes.
>> Yes, maybe you know, you said, in the computed style it is. If the computed style [INDISTINCT].
>> RESIG: Right the time, so maybe this will--at the time that which you call it.
>> So, basically, it loads and I ask a greater style for the development and then I make
it into a bigger or smaller and then I ask a bigger style for the development, I can
equip with the proposal? >> RESIG: Yes, absolutely. Yes.
>> [INDISTINCT]. >> RESIG: Yes. And so I mean there's a lot
of them that are--that the most mind bugling one, is in Safari 2 and 3. And so in Safari
2, if you call to get computer style element--or sorry, a function, you can't, it's null. And
you're like, "Why is it null? It's supposed to be there." And that's because when you
caught on element that is either displaying on or within an element that is displaying
on, it's just is null, for whatever reason. So, Safari 3 came out, and I was so excited,
I'm like, "Great." They're fixing this problem because I know they were going to fix this
problem because this is so annoying. And so, I go on and call get, computer style. It exists.
I'm so happy and so I go to get the value and it's undefined. And they, so they implemented
the interface but they just made a return, undefined now. And the problem is that attributes
can return undefined, normally. And so now, there's no way to differentiate between [INDISTINCT]
should be returning undefined and when it shouldn't be returning undefined. So the only
way--so my horrible abomination was to get the computer style of color, since there'll
always be a color, and check to see if it exists, and if does then that means that we're
outside of an element that is displaying on. I could go on and talk about horrible hacks,
I could do many presentations on that. But so, yes, the--at least this is getting closer
being solved but again that's the case were I think that you just need to have an immense
test case one that you can't write by hand, when you have to literally permute out. And
then the problem comes up of when you do find a fix, how do you know when to find--when
to run that fix. And this is the progression that I see. Users when they start they always
check the user agent, it's the easiest thing. Oh, you know it is MSIE, no one else could
ever report MSIE. And then, you know, the common secondary solution that's proposed
by people like PPK is to track to see if a specific methods exists, which is great. It
works for get element ID, things like that. And then you sort of think, well maybe because
there are quite some problems that fit into that nice method more and like "Well, maybe
I think of an elegant solution." I think you just realized that you should probably just
checking the user agent. Anyway, because for, you know, especially when you're trying to
tackle issues like rendering airs. It's--you just can't, you can't check that with an object.
There is no way to say, you know, are you quirky when you render this thing, you know,
you have to do checks like that. And the issue is you can't rely, you can't say, "Oh, oh,
I'll just check to see if this specific method exists, that only exist in an Explorer 7."
What if another browser comes along and implements that object or what if, how about, what if
a library comes along and implements that object because that is bound to happen and
it'll drive you insane. User agent isn't perfect, I'm not saying it is but it will get you close.
So documentation, I mean, it goes without saying that documentation is natural. But
what I think is really important is something that we've explored is specifically structured
documentation. So, providing a solid format for highly documentation should be run either--there
are sort of a Java doc or--in the case of jQuery we use something, it came to something
called a script doc. But since we've migrated and we're--we had a XML format. But what's
nice about this is when you have a structure formats, you can change it to other structure
formats XML, JSon and you can give to your users, because you're not going to write the
best API browser. I don't think anyone has a perfect API browser because everyone wants
to look at API's in a different way, so what jQuery did, is I built an XML format that
I pump the API out and people took that and made their own browsers, so now there is literally
a proliferation of other API browsers, cheat sheets that are automatically computed and
make with XEL--XELT, a few made desktop widgets, doing translations and all this because there
is a structure format to work with and this people can literally just pull down the latest
XML file and update their widget or their cheat sheet instantly because, you know, they
don't have to go through the documentation and copy and paste so it's literally an API
for your API, giving people the ability to, you know, expand how the API is shown is immensely
powerful. >> Why do you think some XML are not ideal?
>> RESIG: Why is XML not ideal? Ideal is an expressive enough to express what I want in
a JavaScript, that's the short answer, >> I just wanted to know. I have nothing against
you. >> RESIG: Yeah. The XML form, we currently
have it in standardizing in anything, simply because I don't know one has looked at it
just because JavaScript is not Java and you can't document JavaScript using Java doc,
no matter how hard you try, unless you write really in elegant JavaScript. So, yeah, that's
a whole other issue, what we've been trying to tackle and the other issue...
>> What is the issue with scriptdoc or JSdoc? >> RESIG: So the issue was scripted doc or
JS doc, is that you can't--okay. So let's say you want to document what the context
is on a call back function, what if you want to document the arguments of a call back function
like it's passed to a method, what if you want to document properties that gets passed
into an object, I mean, and these are all immensely common cases for JavaScript libraries
and then it's--people just ignore it so--and even people who are at the like the fore fronts,
so like Aptana, they are only a part of the way there, it's a large issue, so, the other
issues, you're going to have your documentation on a structure format and you want people
to help, you want people--you're going to make strong mistakes, you're going to make
code mistakes and people come in and help you out, so, I consider the current solution
I have with us is put in a wiki and you have, yes now you have two problems, at least with
the wiki, my current tactic is to use structure templating aside if you ever done media wiki
templating, that will--that will do something to you. Your structure templating and use
that to generate structured documentation. I'm running out of time so I got to hurry.
So leverage, only--specifically, write the documentation that will help your users the
most and that will help the library the most, cause your time is limited so you should focus
on the best of first. This is a rough order that has, so start with a user API, that will
definitely support it. And then eventually, start to getting writing documentation on
how to write documentation so that other people will come in and they'll know how to do it
and it will self perpetuate. And finally for documentation, you need, if there's no documentation,
you really just have to buckle down and do it yourself. There's really no other way.
So, it's self explanatory, you just have to do it. Testing. Testing is absolutely essential,
and I say, don't trust any library that doesn't have a test week, any Java library especially,
because of all, the fantastically weird, browser bugs that exist, I can't do it, how many bugs
I caught JCreator last week, it puts fear to my heart, and see ones that don't have
it so currently put a type that we can shake for Yahoo, just got one. Writing on sweet,
the pretty easy, make sure it passes all browsers, handle a synchronize test. Test room development
is incredibly important, we use in jQuery all the time, we ran the task first, so this
start failing. And then we read within, it encourages us to make a not fail, so we write
the implementation. And it will be great if there's a way to have pre commit hook in Google
hub, because then we could check to see, if we're passing still, before we commit. Just
the same. I guess I recently wrote a pure JavaScript DOM that runs in Rhino, so that,
you can end and in run--it can run the full jQuery library. There's some more information
about that in my blog, won't go into detail here. So the future testing is will be a multi
browser testing so that you can take a patch, push it to the code base and it will distribute
out into everyone's browser, everyone who's logged in and it will come back with all the
test results and it will come back to you. So you can essentially distribute your load
and your test cases and kind of sort of distribute the future and were starting to explore that
now, we'll see what it leads to. So, maintenance, making easy to tackle new bugs. You should
interact with the community a lot and most importantly this is absolute important is
that, you need to maintain the focus of your library. And, even if it's nothing more than
one semi benevolent dictator, standing over the project, saying, "No, that shouldn't go
in or no, it has to be named that way." You have to do it, otherwise, you're going to
get [INDISTINCT] mess of, I don't know, factory generators or something. You need to, you
need have oversight and you need to maintain focus, and so that's why no more jQuery. Every
time, someone tries to commit, I put them through this horrible goblet and I think it
maintains the focus of the library, pretty well. So, I'm going to open up the questions
and like a couple minutes they have left. >> So we have a mic here for questions.
>> See, your library looks seems very nice but isn't more or less targeted to Firefox
and wouldn't actually be--well a reasonable to use it, say, on a cell phone?
>> RESIG: jQuery? >> Yeah.
>> RESIG: No, a jQuery is cross browser, fuel is Firefox only.
>> Uh, I see. >> RESIG: Yes, jQuery is independent and Safari
23, i67, Firefox 1052 to Opera. >> Yeah, and my cell phone supports IE4.
>> RESIG: Sorry. I'm not going there. >> Um, yes?
>> How do you filter the noise in the community, is that something you guys trouble with like,
just loud and vocal minority or, stuff like that.
>> RESIG: You just, it's hard, you have to use your discretion and I mean, that's really
the advantage of you having a plugin architecture--is that you can say, go make in a plugin, if
your plug in becomes popular, then will bring back in. You know, you tell them to prove
themselves first. And, you know, because there's a lot of people who held like, "Oh man, you
know the, I wish I have this, crazy advance animation that jQuery, no we not even wished
to saying that, it's a, they must be in jQuery. And you just have to say no, you know, because
even, you know, especially for files concise concerns. But, I mean, you say here, go use
his plug in, you know. >> [INDISTINCT]
>> RESIG: So the question regarding [INDISTINCT] and having multiple builds sites, skin just
built, is that what you need? You can do that right now and jQuery build system. There's
it's a make file, you can tailor it. But we definitely want something more advanced and
we're working on it right now, so that you can, pick and choose what parts of jQuery--not
that jQuery's huge, just 20k but at least, pick and choose what plugins you want to include
into your custom build. Yeah, that's definitely--definitely concern.
>> Actually, there's a question right here. >> RESIG: Okay.
>> Do you think there will be a time when library development life is sort of isn't
necessary anymore or do you actually think that the ecosystem of libraries is a good
way for advancing state of the art? >> RESIG: So will it ever change? No, not
in any future that I foresee. That there's no incentive for certain browsers to implement
standardization, it isn't--it simply is a market beneficial for them. So, why should
they become standards compliant because then people can go elsewhere. And--so there's always
going to be differences no matter what and even if there isn't difference, people will
implement their own special methods let's say, like elements by class name, which maybe
only a couple of browsers will implement, but you want a special case to, you know,
to see if that exist and if it does use that fast method, if it doesn't use this other
methods, you know, it's not going away and it doesn't help the ecosystem definitely.
I mean, I've been doing CSS3--I've been using CSS3 now for about two years which is about
two years more than anyone who's ever written the CSS3 specification. It's--yeah, so I can
have a better. Okay, yes. >> [INDISTINCT]
>> RESIG: So how did I pair something like Jquery to something like Google web 2K? Completely
different ball game, so Jquery is pure java script, client side only. And, you know, it
has some AJAX tidbits to communicate but there isn't any, you know, object persistence, you
know, modify the object in the server, go to the client, it's--yeah, it's significantly
different in a--in a lot of ways. All right. Anymore questions? Wait, we got one over here.
>> Right, one in the back. >> Yeah, just out of curiosity, do you have
any information on, what's the largest size project that Jquery is being used and in terms
of size of development team and size of code base roughly?
>> RESIG: Development team and code base. >> I guess to rephrase the question, is Jquery
design more for small one of project so do you think it would be useful for a project
that has like a hundred developers working on some massive system?
>> RESIG: I don't know. I mean, it's definitely--I don't know of any hundred developer teams
that are using Jquery, but it is used--let's see, I don't know, MSNBC, Dig, IBM, Orocom,
Sisco, there's a massive list other the website. It--but most of the teams I'd say largest
maybe a dozen, I don't--yeah, I don't know of any massive teams like that, otherwise
I think we would have seeing contributions coming back from them.
>> [INDISTINCT] >> RESIG: Say, say again?
>> Independent of Jquery has taught of a hundred percent java scripts project that's totally
frightening. >> RESIG: So the thought of a 100% java script
project is frightening and I don't know, I--it's very different definitely. But--yeah, I like
it. And it provides a different level of freedom and especially it brings in people from all
backgrounds, we--so on Jquery we have people coming from cold fusion, PHP, Ruby, Pearl.
I mean, literally they all write different languages in their day-to-day job and--but
they all come and they're--and they--but the java script is as common playground for developers.
And they, you know, it, it's, you know, it's like no man's land, you know, where they going
to, you know, parley. And it's--I mean, I like it, I like the language a lot, and I
think it--I don't know, I like it. >> I think we time for one more question.
>> Okay. Just say few more words about distributing testing [INDISTINCT]
>> RESIG: Okay. So... >> [INDISTINCT]
>> RESIG: Okay. So, distributed testing. So, what we are looking at with that right now
is--so the users would be a sensor sitting on a page that auto refreshes, or, you know,
oppose an AJAX chunk of test and just runs those--that batch of test, you know, with
that specific version of let's say Jquery, and then reports back how many test pass or
failed, you know, or just the results. So, we do this a little bit right now in Mozilla,
we have a--we imported the multi-kit test week, we called multi-task and one of the
things I did is I brought in all the java script library test weeks and I have them
running in this little mini web server, a multi task, so the test week runs and that
is--at AJAX back the results and that is aggravated in to the full Mozilla built system. So, every
time you--now, when you a commit to make a change of firefox, it's you running against
multi-kit prototype spectacular Jquery, all the test weeks. So--I mean, yeah, it's still
pretty experimental but I think, we at least have the foundation. Well, what I ultimately
want to get to is where any lay person can be running this into browser, so that they
can load up, random old version of conqueror, you know, they, could test because that means
something to them. >> Thank you John.
>> RESIG: Yup.