I’m a senior JavaScript engineer at Bocoup, the co-host of the yayQuery podcast, a co-organizer of TXJS, a contributor to the jQuery
Cookbook from O’Reilly, and the author of the open-source jQuery Fundamentals. I speak and write
frequently about JavaScript topics, including talks at JSConf.eu 2010 and
JSConf 2011. I live in Durham, North Carolina, with my partner, our dog Ellie, and
two terrible cats.
This is my blog, but you can also find me elsewhere on the internet:
Update: I’ve written a separate post on the wisdom of rolling your own large application toolkit that incorporates jQuery.
I’ve been thinking a lot lately about JavaScript applications. As my skills have evolved, I’ve had the privilege of working on more actual applications, and I’ve gotten further and further from clients who want to add a bit of Ajax or bling to an otherwise fairly traditional web site.
The most interesting applications I work on are client-side intensive: the server is responsible for providing data as JSON to the client, and most everything else — templating, state management, data management, site navigation, and of course user interaction — is left to the client side.
It’s a lovely way of writing an application. There’s no need for me to touch server-side code; in some cases I work with a server-side developer to decide what the data they send will look like, but in others I just take what an API already provides and make it work. I get to use the same templating framework across projects, regardless of server-side technology, and I can prototype complex interactions before the server side even exists.
This is a land where HTML, CSS, and JavaScript are almost all you need, and I like it. I’ve become a firm believer in moving giant hunks of functionality that used to belong to the server over to the client. For a variety of reasons, I think it’s clear that this is where most interesting web development is headed, to the extent it’s not already there.
This style of building an application changes the front-end development game. In fact, “development” may no longer be an adequate description; we’re moving into the realm of engineering, here. We’re not using JavaScript to add a bit of bling to our sites — a slideshow here, some Ajax there — we’re architecting an application, damnit.
Among a host of questions presented by these sorts of applications, some of the most interesting to me are:
What are the units of functionality that will make up the application?
How will those pieces be organized into units of code?
How will those pieces communicate with each other?
How will dependencies between components be expressed and managed while adhering to the principle of loose coupling?
How will components manifest themselves in the DOM? Do they need to?
How will we persist data across URL and page loads?
How will we manage communication with the server?
How will we make sure users only see the data they’re allowed to see?
At the risk of making a broad generalization, this isn’t the way today’s average JavaScripter learned to think. The mantra of jQuery, the most popular JavaScript library on the internets, is “get some elements, do something with them” — perfectly terrible preparation for analyzing an application from a perspective other than the DOM.
As more and more application logic moves to the browser, I’m eager to see the JavaScript community rise to the challenge, but instead it feels like the opposite is happening. People with little understanding or appreciation of these questions are taking on projects that demand these questions be answered. The result is a land of fragile code that gets the job done while giving the finger to the next developer; a land of code so tightly coupled, so deeply beholden to the DOM, so blatantly not reusable or extensible or maintainable as to render every subsequent commit a complete crapshoot, as liable to cripple the application as not. The viability of the project is threatened, and so is the reputation of JavaScript.
We are better than this. JavaScript, even that old-fashioned browser kind, is a language worthy of respect, not a thing to be dreaded. But — and here’s the sentence I have struggled 10 months to realize and an hour to write: in order to prove that we are better than this, we must make abundantly clear to the budding developers, to the project managers, to the enterprises, to anyone intending to build a remotely complex JavaScript application, that there’s more to JavaScript than jQuery. The questions are bigger, the answers more complex, and the relevant skills, alas, a bit harder to come by.
We have to make clear that, in fact, jQuery is but a hammer. When it comes to building these intensively client-side applications, we’re talking about building skyscrapers, for god’s sake. The problems solved by a hammer are the least of our concerns.
It was just a few months ago that I gave a presentation on building large jQuery applications. I emphasized jQuery’s role as strictly a DOM and Ajax tool, and demonstrated a few other tools — John Resig’s simple inheritance, James Burke’s RequireJS dependency management and build tool, Jan Lenhardt’s mustache.js — that one would want to bring to the table for such an undertaking.
But to what end do we assemble said hodgepodge of tools? Is it just so we can continue to “use jQuery”?
jQuery’s API is, indeed, dead-simple, but we are smart people! We are building skyscrapers! When it’s time to write a complex application, and we need all of these things that jQuery doesn’t offer, can we not learn to use another hammer — learn that dojo.place('
I am new!
', oldDomElement, 'last') means the same thing as $('
I am new!
').appendTo(oldDomElement) — if learning it gives us access to legions more functionality than jQuery even aspires to provide?
Do we assemble this hodgepodge because finding jQuery developers is perceived as an easier task than finding practitioners of another library, even though someone saying they “know jQuery” is little indication that they will know how to work with the assembled solution?
Do we do it for the plugin ecosystem — full of code of varying quality and maintenance — even though many of the large application needs addressed by those plugins are addressed by other libraries as well, and sometimes better?
And when we do it, when we assemble this collection of tools ourselves, what risks are we accepting? What price will we pay down the road to maintain three or five or 10 different pieces from three or five or 10 different authors, with different release cycles, no guarantee of compatibility or maintenance, and no central project thoughtfully considering their future?
I’ve wrestled with these questions for months, agonizing during sleepless early-morning hours over how to advise clients on the answers. I’m the co-host of yayQuery, a contributor to the jQuery Cookbook, and, I’ll venture to say, a decently respected member of the jQuery community. I did not arrive at this conclusion lightly, and I have few illusions it will be well-received, or even heeded.
But I’ve grown weary of people championing a tool that simply does not answer the big questions I see in project after intensively client-side project. I’ve grown weary of those same people dismissing tools that answer those questions handily and have been answering them for a while now. I cringe when clients tell me they’ve chosen jQuery because it was “easy,” and then watch them predictably struggle with all of the questions it does not answer. And I’ve found I can’t continue to bite my tongue when people recommend jQuery as an enterprise-grade solution while failing to acknowledge these questions, let alone answer them*.
I do not want to see jQuery go away. The simplicity of its API was undeniably instrumental in the rise of JavaScript as a language these last few years. It is a perfect gateway drug, and I greatly enjoy watching people transition from “get some elements, do something with them” to the elegant patterns of JavaScript itself.
jQuery is an entirely appropriate answer to so many questions, but it falls so short for large applications, forcing you to assemble such a tenuous toolkit of your own, that it simply isn’t a viable answer — or, in my opinion, part of an answer — for large applications. If we hope to continue to gain respect as a community, we ought to admire jQuery’s immense contributions, but we must not be afraid to accept and make very clear its limitations. We do otherwise at our peril.
*An aside: To its credit, JupiterIT has put forward JavaScriptMVC, the only substantive attempt I’ve seen at answering these large application questions using jQuery. I applaud them, but fear their efforts will continue to be somewhat isolated without the support and endorsement of the wider jQuery community. If you have read this far and still have your heart set on a jQuery-centric large application solution, you should by all means take a look at JavaScriptMVC.
Over the weekend, there was a tweet announcing that Google was going to provide “scholarships” to qualified women to attend JSConf.eu. There was then a tweet by another person calling this “disgusting” and “illegal.” Nicole Sullivan has a level-headed and well-articulated roundup of the back-and-forth and some of the surrounding issues, and I suggest you read it.
I take no position on the scholarships. I question whether they will have any meaningful or lasting effect. I fear the availability of the scholarships will lead to ill feelings about the women who do attend. Simultaneously, I yearn to discover, against hope, that they make it possible for some highly qualified but unknown woman to gain access to the JavaScript community. Whatever. Smarter people than me have a better idea than I do as to how effective they will be, and lawyers can tell you whether they’re illegal. I’ll stand firmly in the “no” camp on the disgusting count.
You know what’s disgusting? Being groped at a conference after-party by a drunk married man. Opening your hotel door to discover said drunk married man stumbling down the hall, asking himself into your room, and literally having to slam the door in his face.  Seeing someone ask, publicly, on Twitter, if anyone knows the name of the hot conference chick.
I adore my male friends in the tech community. They have encouraged and supported me and welcomed me into their inner circles. But even they can act like 12-year-old boys sometimes, and while I don’t begrudge them that, it is hard, because it’s at those moments that I realize how much I am not them, how much I long to have more than the barest assembly of female peers who have any idea what this is like.  If Google wants to pay them a measly few hundred bucks to put up with it, maybe that’s OK. Hell, maybe they ought to pay them more.
I am angry. I have been angry since Saturday, when this all started. I have spent the last year trying to be the thing that I want to see: the woman on stage. I have formed groups to encourage other women to do the same. I have reached out to women who show potential and tried to give them the encouraging nudge they need that no one really gave me. And right this very moment, I feel incredibly selfish. This weekend reminded me what I am asking those women to enter into: a world that presents no tangible barriers, but that will objectify them every step of the way.
Men, guys, boys: I am not asking you to give up Star Wars and The Matrix. I’m not even asking you to give up gratuitous phallic references and #twss jokes, though I hope we’re all grown-up enough to know that there’s a time and a place. And you know what? If you want to DM your friend about trying to hook up with that hot conference chick, well, good luck with that. We’re all human. But for the love of all that is good: this being a woman in your world thing, it’s not easy, OK? Maybe you can’t understand it, and I even believe it when you say you don’t mean it.
I came across a little code the other day that reminded me I’ve been meaning to write about JavaScript patterns I take for granted. The code in question was intended to set the value of some fields in a form when a checkbox was selected; when it was deselected, the same fields were to be emptied. It looked not unlike this:
1234567891011121314
// config is defined outside of this snippet,// and may contain more than the properties// we care about $('#myCheckbox').click(function(){if(this.checked){$('#field_foo').val(config.foo);$('#field_bar').val(config.bar);$('#field_baz').val(config.baz);}else{$('#field_foo').val('');$('#field_bar').val('');$('#field_baz').val('');}});
This is a wholly readable bit of code – there’s almost no question what’s going on here. On the other hand, it’s pretty easy to see the rampant repetition; this code isn’t interested in “don’t repeat yourself” (DRY). We’re calling the same method on every selection we make, and our selections are repeated in both the if and else block. When I saw this code, I had an immediate inclination to rewrite it. Here’s what I came up with first:
123456789101112131415161718
// config is defined outside of this snippet,// and may contain more than the properties// we care about$('#myCheckbox').click(function(){// note whether the checkbox is checkedvarchecked=this.checked;// iterate over the keys we care about$.each(['foo','bar','baz'],function(i,v){// find the field for the given key$('#field_'+v)// and set its value either to the string// stored for the key, or to an empty string,// depending on whether the checkbox was checked.val(checked?config[v]:'');});});
This looks approximately nothing like the initial code, and without the
comments, the code itself would be substantially less readable than the
original. The idealistic part of me – the part that believes people who write
JavaScript should understand JavaScript – says this is an acceptable price to
pay. And besides, there’s something to be said for explaining the code in a
comment that can be stripped by a minifier, rather than explaining the code via
the code. In this iteration, we’ve introduced two patterns for DRY-er code:
iterating over an array literal (or, alternately, an object) to achieve
repetition without repeating ourselves, and using the ternary operator in place
of an if/else statement when the simplicity of our logic allows it. The array
literal serves as a list of the fields we care about. When our checkbox is
clicked, we iterate over this list, build up a selector for each item in the
list, make our selection, and then set the field value using a ternary
operator. We’ve gone from 11 lines of code to six, with the added bonus
that we have to do a lot less typing if we need our checkbox to affect more
fields.
(A side note: Is this premature optimization? I’d argue no, if you’ve
learn to see these patterns before you start writing code. Once you learn how
to spot these patterns in a requirement, writing code that embraces them can
actually be easier than writing code that takes a more “literal” approach to
the problem. For example, imagine if the checkbox affected 20 other fields
instead of one? You’d undoubtedly find yourself copying and pasting code if you
took the more “literal” approach to the problem, and that would be your first
clue that you were doing something inefficiently.)
The great thing about using a pattern like this is that it rapidly exposes the
actual meat of what you’re doing, and makes refactoring far less painful. I
also find that it helps me see opportunities for reuse that I might not have
spotted in the more literal version of the code. Let’s say we’re feeling all
proud of ourselves for DRYing out our code using clever JavaScript that only
super-smart people can read. Now there’s another checkbox that needs similar
behavior, but it’s going to use a different config object and a different list
of fields. No problem! You’ve already written this code, so you can just copy
and paste it and then change what’s different. Sweet. Er … suddenly you’re
not looking so DRY after all. This is when another pattern comes into play:
creating a function that returns another function with certain variables
already baked in (that is, creating a closure). We’ll execute this creator
function and then use the function it returns in place of the anonymous
function we were using previously when we bound to the click event.
// handleClick accepts a config object// and a makeSelector function; it returns// a function that can be bound to// a click event, using the config object// and the makeSelector function to react// appropriately to the clickvarhandleClick=function(fields,config,makeSelector){returnfunction(){varchecked=this.checked;fields&&$.each(fields,function(i,v){// build the selector using the provided// makeSelector function$(makeSelector(v))// set the value using the// config object, depending// on whether the checkbox// is checked.val(checked?config[v]:'');});};};$('#myCheckbox').click(// use handleClick to create a function// that has these variables baked in;// pass the created function as the// click handling functionhandleClick(['foo','bar','baz'],myCheckboxConfig,function(field){return'#field_'+field;}));$('#myOtherCheckbox').click(handleClick(['bim','bar','bop'],myOtherCheckboxConfig,function(field){return'input[name="'+field+'"]';}));
By creating a function that returns a function, we can isolate what’s different about the two different handlers while centralizing the pieces that are the same. If your event handling function was slightly less trivial than this one, or if you were binding to five different checkboxes instead of two, the benefit of consolidating the code would be even more substantial. JavaScript offers plenty of patterns for writing DRY-er code; it’s important to learn to both recognize and use them. It’s also important to recognize when you’re writing un-DRY code in the first place – copying and pasting code is one crystal-clear indicator, but others are more subtle and you may not identify them on the first go-round. For example, take these two functions; each receives a list item as its only argument and returns either the next or previous list item, returning to the beginning or end of the list if there is no next or previous item.
This felt repetitive when I first wrote it, but I couldn’t quickly come up with a single function that would work. A little thinking about it, though, led me to this single function which gets a second argument: direction. That argument is used to decide whether to run the item’s next or previous method, and then whether to run the item’s first or last method. Besides combining two functions into one, it also eliminates calling next or prev twice inside each function.
Learning about patterns and then discovering opportunities to use them is one of the more pleasing parts of my job. I hope this helps you identify some of those opportunities for yourself :)
I’ve been leading jQuery trainings for more than a year now, from tiny gatherings that I organized myself at the local coworking space, to intensive two-day sessions at local web companies, to whirlwind one-day classes at governmental agencies. Over the course of those trainings, I’ve developed what I’d like to think is a decent curriculum – training material that’s the size of a small book, exercises that demonstrate core concepts, and solutions to those exercises that students can peek at later or when they get stuck.
I decided recently that it was time for all of this material to see the light of day, so I spent the last several days converting it all to DocBook files that allow for easy publication to HTML and PDF (and other formats, if I’m later so inclined). I also fleshed out some topics that I’d given short shrift, and started planning sections covering advanced topics such as plugin authoring, code organization, best practices, and more. There’s more to come in the next few days, but I think what I’ve done so far is worth sharing. I hope you’ll agree.
GitHub repo (exercises, solutions, and book source code)
My goals in releasing this are several. First and foremost, I want to see people writing better jQuery. The free resources for learning jQuery are scattered across the internets, and my personal experience of learning the library was haphazard — it was a long time before I learned some things I wish I’d known from the get-go. In addition, I want people who are writing jQuery to understand JavaScript. To that end, the book begins with a survey of JavaScript itself before jumping into jQuery. Finally, I want to enlist the bright minds of the jQuery community to help developing a robust, authoritative, in-depth jQuery curriculum, and in exchange it only seemed fair to make it available to everyone.
I should mention that the goal of this material is to serve as a companion to a human instructor. That said, individuals may find it useful for self-study, especially if they’re diligent about doing the exercises at the end of each chapter.
If you’re inclined to help – by adding a chapter, a section, a paragraph, an exercise, or even just a correction – fork the repo and send me a pull request. I look forward to seeing how this project might evolve with the community’s help.
Note: If you comment on this post pointing out an issue with the material, I will do my best to tend to the issue, but I probably won’t publish your comment, as this post isn’t the right place for reporting issues in the code. You can report issues at the repository, but if it’s important to you, please fork the repository, make the change, and send me a pull request.
I just got done with an emergency project for an agency developing a public-facing application for a mutinational technology client you’ve most certainly heard of. I developed the entire front-end – HTML, CSS, and JavaScript – for a non-trivial application with a limited spec in just seven days. The experience was so eye-opening that I feel the need to write down some of the things I’ve learned, in hopes that I can benefit from my experience in the future.
Demand all technical source material up front, such as functional specs, mockups, work that’s been done to date, etc. Give the client a fixed amount of time to deliver that source material, and don’t make a decision about taking on the project until you’ve seen it. What the client can deliver in that fixed amount of time will shed a lot of light on the state of the project and whether their expectations are realistic.
Set clear time expectations. Am I willing to work 16 hours a day? Am I expected to? Are there hours during which I’ll be expected to be available? Am I willing to work on the weekend?
Find out whether the client expects me to be available after the imminent deadline, and to what extent. The last thing I want is to snatch defeat from the jaws of victory by being unable to support the code I’ve written.
Do not accept responsibility for commitments made on my behalf. The recruiter said I’d be available six hours a day when I told him four? Not my problem. The client committed to having a feature ready for review without consulting me? They probably won’t make that mistake again.
Ascertain the rest of the team’s commitment to the project. If I’m expected to work long hours, will they be there during those long hours to get me what I need? Are there any constraints on their availability?
Establish a single point of contact at the client, and make clear I’ll be depending on them to get me any information I need and I’ll be treating their decisions as final. Insist that they participate in all calls I’m expected to participate in.
Limit the amount of work I do before I have access to all client systems I’ll need access to: version control, testing environments, ticketing systems, etc.
Insist on a ticketing system. I’m new to the project and I have a lot to get up to speed on. I don’t want emails flying at me from all directions – decisions and technical requirements need to be documented in a single place that everyone can see. This is my only insurance when someone wants to know why something isn’t done, or why it wasn’t done the way they expected.
Insist on version control, even if it’s something crappy like CVS. I’ll need a way to make sure the rest of the team has access to my latest and greatest. FTP blows, especially when I’m FTPing to a server where another developer is constantly deploying a new build, overwriting my work.
If you follow me on Twitter, you’ve heard about TXJS by now, but let me tell you: now that we’ve announced Douglas Crockford and John Resig, there is officially no way you should miss this. TXJS is a full-day conference set for June 5 in Austin, Texas, hosted by the yayQuery team and featuring BBQ and a slew of awesome JavaScripters:
Brandon Aaron, jQuery team member
Tim Caswell, Node.js contributor and founder of howtonode.org
Douglas Crockford, JavaScript architect at Yahoo! and author of “JavaScript: The Good Parts”
Andrew Dupont, Prototype core team member
Peter Higgins, Dojo project lead
Paul Irish, jQuery team member and yayQuery podcast co-host
Brian LeRoux, software architect at Nitobi and PhoneGap hacker/contributor
Joe McCann, senior technologist at Frog Design
John Resig, creator of the jQuery JavaScript library
Alex Sexton, front-end developer and yayQuery podcast co-host
Kyle Simpson, Austin JS organizer and author of LABjs
Adam Sontag, jQuery UI developer relations team member and yayQuery podcast co-host
Mike Taylor, HTML5 aficionado and front-end developer at Tunecore
This is a reprint of an article that originally appeared in the October
issue of JSMag.
I recently had the opportunity to architect the front-end of a new web
application from scratch, and after years of using jQuery, I decided to give Dojo a try. For a variety of reasons —
not least of which was Dojo’s approach to code organization and
dependency management — I thought this would be a good project to get
some real-world Dojo experience under my belt. What follows is an overview of
Dojo from the perspective of an avid jQuery user. I’ve been using jQuery
for years. Its simplicity is seductive; after a while, it kind of writes
itself. And maybe that was my problem: I was ready to try something new. Many
months ago, I wrote on Twitter that I was interested in learning more about
Dojo. Rey Bango, jQuery evangelist,
wrote back, and put me in touch with Pete Higgins, the Dojo project lead.
Pete proceeded to lobby me for months to give his “unified toolkit”
a try. I dabbled. I read the docs. Pete plied me with sample code to show me
what I was missing, and even drove to North Carolina to lead a Dojo camp. In
August, I decided it was time to stop dabbling and dive in. I’d just
finished writing some essentially library-less JavaScript for a web-based
iPhone application, a task that left me much more confident in my knowledge of
JavaScript. With the mobile site out of the way, the client was ready to build
the desktop version, and I would be in charge of the front end. It was time
to choose a library; this time, I chose Dojo.
Deciding on Dojo
The decision to try a new library on a client project was a tough one
— I knew that I could write the basic functionality of the site using
jQuery a whole lot faster than I would write it with Dojo, simply because I
knew my way around jQuery so much better. Using Dojo would mean I’d be
looking up a lot of things, from simple stuff like how to work with DOM
selections, to more complicated tasks like how to structure my code for the
purposes of reuse and abstraction. As my work on the project progressed and
the deadline neared, I had plenty of second thoughts. A few things convinced me
to stick with Dojo when the going got tough:
Code organization
patterns: Dojo provides pretty clear guidance on structuring both your features
and your codebase. I’ve given a lot of thought to organizing jQuery code.
I wrote an article on the topic for JSMag and gave a presentation on the topic
at the jQuery conference. I was eager to try a library that explicitly answers
the organization question.
Class inheritance: I knew from the start
that I was going to use a lot of interaction patterns over and over. I wanted
to be able to write those patterns in a way that would let me use them across
features while still staying DRY. The class inheritance provided by
dojo.declare() was an elegant, easy-to-use solution to the
problem.
Dependency management: Being able to easily manage
dependencies was a huge draw for me; it promotes reuse and abstraction in a big
way. Dojo’s dependency management would also pave the way to easily
building production-ready files that would combine all the necessary
functionality for a given type of page, reducing the number of HTTP requests
required.
Service method descriptions: This particular application
relied on XHRs (AJAX) in a big way. Dojo’s service method description
approach would let me manage the URLs and parameters for those requests in a
single place, keeping pieces that might change separate from the core code.
Eventually, theoretically, the server-side code could actually generate this
SMD file automatically. More on this in a bit.
Templating: All the XHR
responses were JSON, which I’d need to turn into HTML. jQuery has
templating plugins to solve this problem, so this wasn’t really a
differentiating factor, but nonetheless it was going to make my life easier. I
could maintain the templates for turning JSON into HTML separately from my
JavaScript, and even programmatically choose the template depending on the
situation.
The meaning of this: When binding a function
to an event on an element in jQuery, this inside the function
refers to the element that triggered the event. This is arguably desirable for
simple code, but when you start organizing your code into objects with methods
and you want this to refer to the object, not the element, it can get painful.
The dojo.hitch() method lets you cleanly change the meaning of
this for any given function, and it’s transparently rolled into other
methods, such as dojo.connect() for event binding.
Documentation and support: Dojo has a reputation for poor documentation,
and to some extent it’s deserved. Their documentation is a whole lot
harder to use than jQuery’s because, at first glance, it’s quite a
bit more scattered and substantially more API-based than task-based. However,
once I figured out where to
look for the docs I needed, finding answers to my questions was pretty
painless. I also leaned heavily on some experienced Dojo developers for
guidance and support, and dropped in to the ever-helpful #dojo IRC channel on
Freenode if I got stuck.
Getting Started
The first step was assembling my new toy. I opted to use the library via
Google’s CDN so I could get up and running as quickly as possible. After
that, it was time to figure out how I’d organize my files. Dojo
actively supports namespaces for components, which means you can put your
application files in one or more directories and associate your namespaces with
those directories. I created a high-level controller file in the root /js
directory; it would be responsible for figuring out which functionality was
required for a given page (a decision I’ll eventually revisit). Then, I
created a directory inside the root /js directory, where I’d put all of
the individual files for the various components.
Finally, I included a line in my controller file to tell Dojo where to find
the namespace I’d be using: dojo.registerModulePath('myNamespace',
'../js/myNamespace'); Figuring out all of these pieces may have been the
hardest part of making the switch to Dojo — it was a whole lot more setup
than I was used to with jQuery, and though it is all documented, it took a bit
of effort to find the details and to get the paths set up correctly. The time
it took to get everything working properly was time that I spent wondering
whether I’d made a good decision. Once it was working, it was time to
write some actual code and try to answer that question.
 In jQuery, you query the DOM using a
CSS selector, and the result of that query is a jQuery object, which you can
then operate on using method chains. It’s fairly rare in jQuery to work
directly with a DOM element. While Dojo supports this paradigm through its
dojo.query() method and the NodeList it returns, it’s common in Dojo to
work directly with a DOM element rather than a NodeList. My initial
inclination was to stick with what I knew from jQuery, and to use
dojo.query() to get everything I wanted to work with. As I dug in,
though, I discovered that it could actually be just as elegant (and less
expensive) to work directly with DOM elements, even though they didn’t
come with any of the magic of a jQuery object. The syntax for doing so was a
bit different — for example, dojo.addClass(myDomElement,
‘foo’) instead of
$(myDomElement).addClass(‘foo’) — but the more
code I wrote, the more frequently and easily I found myself using the
dojo.addClass syntax instead. Embracing this approach was especially valuable
when it came to methods that returned something. For example, the
dojo.connect() method (used to connect events to elements, similar
to $().bind()) returns a connection object, which can be stored
and disconnected later without having to know which element the event was
attached to. This is, in a word, awesome. It’s also an example of how
Dojo requires you to think somewhat differently about how you write your
JavaScript.
Returning a Result For the Win
Along those lines, I had to get used to the fact that a lot of Dojo methods
returned objects that I could talk to later. For example,
dojo.animateProperty() created an animation object which could
later be play()’d. All of the XHR methods — and asynchronous
methods in general — returned a “deferred” object, to which I
could later add success and failure callbacks. jQuery does return the native
XHR object from its $.ajax() method, so you can technically add
callbacks there too. What I liked about Dojo’s deferred approach is that
it provides a common, simple interface for interacting with all asynchronous
operations, and even lets you define your own. Getting the hang of how to take
advantage of these things took some doing, coming from the more procedural,
chained world of jQuery, where just about everything returns a jQuery object.
Soon, though, I was setting up animations long before I was ready to play them,
and adding callbacks to XHRs after they started.
SMDs: A Unified Way to Talk to the Server
One thing I really wanted to try with Dojo was making use of Service Method
Descriptions, or SMDs. An SMD file basically contains information about all of
the services provided by a resource. In my case, the resource was the
server-side application, which I’d be communicating with to request JSON
data. By creating an SMD file, and then instantiating a new Service based on
that file, I could create a single place for managing all the paths and
parameters I’d use to get what I needed from the server. When I asked the
server for something, the Service I created would return a deferred object, to
which I could attach callbacks. In the background, Dojo was just running an
XHR, but my individual classes didn’t have to worry about the details
— I just had to worry about the name of the method and the parameters it
required, and the Service I’d defined and instantiated would take care of
the rest. For my initial work, I just created the SMD file by hand, but
eventually it’s easy to see how the SMD could be generated by the
server-side application itself. Here’s a sample SMD (normally an SMD would
have a lot more services, obviously):
I love jQuery, I do, but this is an area where it is sorely lacking. It
offers little guidance on how to structure your codebase, how to ensure that
everything you need is loaded, or how to build your code into production-ready
files. Dojo really shines here, but again, it takes a bit of getting used to.
The base dojo.js includes a ton of basic functionality, but I had to quickly
learn to dojo.require() additional functionality as I needed it. In jQuery,
you’d do this simply by adding another script tag to your HTML;
dojo.require() basically does this for you programmatically, but checks to see
that the required code hasn’t already been included first. This means
each of your components can require exactly what it needs, and it’s
perfectly safe to require the same thing more than once. The flip side of this
is that if you forget to require something you need, or if you require it using
the wrong name, it’s not always clear exactly where you made the mistake.
Each file that will be dojo.require()’d begins with a
dojo.provide() statement, telling the dependency management system
that it has, indeed, found the right file. After that, the file can go on to
dojo.require() its own dependencies, which Dojo loads before
proceeding with the rest of the file’s code. The
dojo.provide() method also sets up the object chain along the
path; for example, if you dojo.provide(‘a.b.c.d’), you
can then safely do a.b.c.d.e = { ... }. When it comes time to
assemble your individual files into production-ready, combined, minified files,
Dojo’s build system is able to parse dojo.require()
statements and automatically include the appropriate files; with jQuery, this
is a much more manual process that can be difficult to maintain. Creating a
build wasn’t as straightforward as I’d hoped it would be, and I
stumbed a lot along the way. It took a bit of doing to get all of the paths
just right, and to figure out how to have a repeatable build process that we
could roll up into our full release process. The payoff was big, though: I
could keep my files organized how I wanted them, but only serve one file in
production. The build system figured out the steps in between.
Organization, Inheritance and Abstraction
As I mentioned above, code organization has been a big issue for me with
jQuery. I’ve developed some patterns that I use to keep my code sane, but
plenty of other jQuery developers have not, which can make working with other
people’s code rather painful. While it’s certainly possible to
write procedural, disorganized code with Dojo, dojo.declare()
provides a clear way to avoid it. I talked earlier about creating a namespace
for my code and an associated directory. When it came time to start writing, I
created individual files in that directory for each component on the page.
Inside each file, I indicated which component the file was providing via
dojo.provide(), loaded any dependencies via
dojo.require(), and then created a class in the namespace using
dojo.declare(). The dojo.declare() method takes
three arguments: the name of the class you want to create
(‘myNamespace.Thinger’), other classes you want to
“mix in” to your new class (if any — this argument can be
null, a single class, or an array of classes), and, lastly, an object that
defines the class methods and properties. The result is a class that can be
instantiated using new myNamespace.Thinger(); the object
that’s created encapsulates all the behaviors and states associated with
a particular Thinger, and you can have as many instances of Thinger as you
want. The mixing in thing is huge, because it lets you have a class that
incorporates methods defined in another class. For example, I created a class
called myNamespace.Toggler that would show either the first item in a list or
all of the items in a list; clicking on the first list item would toggle
between the behaviors. Once the myNamespace.Toggler class was created, other
classes could inherit its behavior simply by passing a reference to the
myNamespace.Toggler class as the second argument of
dojo.declare(). I was able to encapsulate the Toggler behavior in
a reusable way, and keep the code for the classes that inherited the Toggler
behavior nice and clean.
Event Management
I mentioned earlier that Dojo has a slightly different take on event binding
than jQuery. I should also say that you can bind events to entire NodeLists
(the result of dojo.query()) if you want, using
.connect() (or convenience methods like .onclick(),
etc.). However, if you want a reference to the connection for later use,
dojo.connect() is your friend. I created a component using
dojo.declare() that was responsible for managing user interaction
with a star rating UI element. I used dojo.connect() to hook up
some mouseover/mouseout behaviors to the element, and stored the returned
connections as properties of the component. When the element was clicked, I
registered the rating, and I wanted the mouseover/mouseout behaviors to go
away; eliminating them was simply a matter of dojo.disconnect()-ing the stored
connections.
Publish and Subscribe
With all of the XHR traffic occurring on the page, I wanted a way to shut it
off if the user was inactive for a little while, but I didn’t want to
write the code for handling that inside every component that used XHR.
Dojo’s pub/sub tools offered the perfect answer. I created a new
component whose sole purpose was to watch for inactivity; when it discovered
inactivity, it would dojo.publish(‘/user/inactive’).
Then, other components — the ones I’d already written, and ones I
write in the future — could subscribe to the /user/inactive topic and
react accordingly. Pub/sub is an excellent way to allow this sort of abstract
communication between components. The component that publishes a
“topic” doesn’t care who’s listening; the component
that subscribes to a topic doesn’t care which component sent it.
It’s another example of how Dojo leads you to think a bit differently
about how you architect your applications — knowing about pub/sub can
help you write much more loosely coupled code.
What I Missed from jQuery
jQuery’s event delegation-related methods .live() and
.is() were hard to live without. There’s a reasonable way to
mimic .is(), but no out-of-the-box replacement for
.live() — you end up writing your event delegation yourself.
Dojo does have dojo.behavior(), which automatically binds event
handlers to elements that match a given selector as they’re added to the
page; however, the event handlers are bound to individual elements, and
there’s no way to provide a context to the selector that you pass to
dojo.behavior(). This may be my noob-ness talking, or maybe
I’m just used to the error messages I’d see when I did something
wrong with jQuery, but I often found myself feeling that the error messages
from Dojo were too cryptic. Worse, sometimes I’d do something wrong and
it would seem to fail silently. I spent a lot more time in Firebug tracking
down the errors of my ways. In general, the thing I really missed from jQuery
was the “it just works” aspect of the library. I expect that with
time I’ll feel that way about Dojo, but in the meantime there are
definitely growing pains. I had to constantly remind myself that the way to
solve a problem in Dojo might not be the same way I’d solve it in jQuery.
More than once I rewrote a slew of code when I discovered some Dojo methodology
or approach I hadn’t known about before.
Conclusion
Lest Rey worry that he never should have introduced me to Pete in the first
place, fear not: I don’t expect to give up jQuery anytime soon. If
anything, I’m excited to see how the library and the community mature and
start answering some of the organization and dependency management questions I
mentioned above. As a library, jQuery most definitely has its place; it has
virtually no barriers to entry and it has helped usher in an era where
it’s dead-simple to create rich, interactive websites. Deciding to use
Dojo instead was something of a gamble. I had to convince the project lead that
it was a good decision, which was challenging considering the popularity of the
jQuery library. He asked lots of pointed questions about the maintainability of
the code if I were to leave the project, and those questions were well
deserved. If anything, though, I think that choosing Dojo has actually
increased the maintainability of the code by presenting clear patterns for
organization, abstraction, and dependency management. Did it take a while to
come up to speed with Dojo? For sure. Will a jQuery developer off the street be
able to jump right in to the code I wrote? Possibly not. At the end of the day,
though, it is just JavaScript, and any skilled JavaScript developer should be
able to find their way around. They’ll almost certainly find, given an
hour or two, that the code I wrote is easier to follow than some of the jQuery
code I’ve run into that doesn’t make use of good organizing
principles. In the meantime, I hope to be working on the project for a while
to come, and I expect the trouble I went through to come up to speed on Dojo
will pay big dividends as the application I’m working on grows and
matures.
In this our first episode of the official yayQuery Podcast, Paul Irish, Adam J. Sontag, Alex Sexton and I stayed up way too late on Monday night and had ridiculous amounts of fun talking about:
Underscore.js, the new functional programming JavaScript library.
The demise of Thickbox (and some good, modern alternatives).
Using (or not using) jQuery for mobile development.
Paul Irish’s antipattern of the week: css(key, value)
Perhaps because it was so late when we finished, there was also chair dancing. Make sure you don’t miss it, but don’t fast-forward to the end or you’ll miss the good stuff.
This is our first try with this, and who knows what will become of it, but we’re very grateful for any and all feedback. You can find us on Twitter @yayQuery, or on the #jquery IRC channel. Enjoy!
This is a reprint of an article that originally appeared in the March 2009 issue of JSMag.
When you move beyond simple snippets of jQuery and start developing more complex user interactions, your code can quickly become unwieldy and difficult to debug. This article shows you how to start thinking about these interactions in terms of the bits of behavior the feature comprises, using the object literal pattern.
In the past few years, JavaScript libraries have given beginning developers the ability to add elaborate interactions to their sites. Some, like jQuery, have a syntax so simple that people with zero programming experience can quickly add bells and whistles to their pages. Adding all those bells and whistles, even some pretty elaborate ones, seems to be just a few Google searches away. A copy here, a paste there, a plugin or a few dozen lines of custom code — the client is duly impressed, and you’re adding jQuery to your resume.
But wait. Now the requirements have changed. Now the thing that needed to work for three elements needs to work for ten. Now your code needs to be reused for a slightly different application where all the IDs are different. We’ve all seen the snippets that make jQuery (and other libraries) look dead-simple. What those snippets leave out — and hey, they’re just snippets, right? — is how to design your code when your needs go beyond dropping in a plugin or doing some show() and hide().
Introducing the Object Literal pattern
The object literal pattern offers a way to organize code by the behaviors it comprises. It’s also a means to keep your code from “polluting the global namespace,” which is a good practice for all projects and imperative for larger ones. It forces you to think at the outset about what your code will do and what pieces need to be in place in order for you to do it. An object literal is a way to encapsulate related behaviors, as shown here:
123456789
varmyObjectLiteral={myBehavior1:function(){/* do something */},myBehavior2:function(){/* do something else */}};
As an artificially simplistic example, suppose you had the jQuery shown in Listing 2 for showing and hiding content when a list item was clicked.
Simple enough, and yet even in this example there are several things you might want to change later — for example, the way you determine the URL for loading the content, the destination of the loaded content, or the show and hide behavior. An object literal representation of the feature cleanly separates these aspects. It might look like this:
Because the initial example was incredibly simplistic, the object literal incarnation is longer. Truth be told, the object literal method generally won’t save you lines of code. What it will save is headaches. By using an object literal, we’ve broken our code into its logical parts, making it easy to locate the things we might want to change down the road. We’ve made our feature extendable, by providing the ability to pass in overrides to the default configuration. And, we’ve done some limited self-documentation — it’s easy to see at a glance what the feature does. As your needs grow beyond the simplicity of this example the benefits of the structure will become clearer, as you’ll see below.
Our mission will be to create a UI element that features multiple pieces of content divided into several sections. Clicking on a section will show a list of items in the section; clicking on an item in the left nav will show the item in the content area. Whenever a section is shown, the first item in the section should be shown. The first section should be shown when the page loads.
Step 1: Crafting the HTML
Writing good semantic HTML is a crucial prerequisite to writing good JavaScript, so let’s start by thinking about what the HTML for something like this might look like. The HTML should:
Make sense (and work) when JavaScript isn’t available.
Provide a predictable DOM to which we can attach JavaScript.
Avoid unnecessary IDs and classes (and you might be surprised by how few are necessary).
With those guidelines in mind, we’ll start with this html.

This is My Nifty Feature
<divid="myFeature"><ulclass="sections">

<ahref="/section/1">Section 1

<ahref="/section/1/content/1">Section 1 Title 1

The excerpt content for Content Item 1

<ahref="/section/1/content/2">Section 1 Title 2

The excerpt content for Content Item 2

<ahref="/section/1/content/3">Section 1 Title 3

The excerpt content for Content Item 3

<ahref="/section/2">Section 2

<ahref="/section/2/content/1">Section 2 Title 1

The excerpt content for Content Item 1

<ahref="/section/2/content/2">Section 2 Title 2

The excerpt content for Content Item 2

<ahref="/section/2/content/3">Section 2 Title 3

The excerpt content for Content Item 3

<ahref="/section/3">Section 3

<ahref="/section/3/content/1">Section 3 Title 1

The excerpt content for Content Item 1

<ahref="/section/3/content/2">Section 3 Title 2

The excerpt content for Content Item 2

<ahref="/section/3/content/3">Section 3 Title 3

The excerpt content for Content Item 3

Note that we haven’t included any markup to display the section navigation or the item navigation; those pieces will be added by jQuery since they will only work with jQuery; non-JavaScript users will get nice semantic markup. (If there’s anything surprising or confusing in that HTML, now would be a good time to read up on POSH (plain-old semantic HTML) and progressive enhancement.)
Step 2: Scaffolding the Object
My first step in creating an object for a feature is to create “stubs” within the object. Stubs are basically placeholders; they’re the outline for the feature we’re going to build. Our object will have the following methods:
myFeature.init() will run on $(document).ready(). It will turn the semantic HTML we start with into a JavaScript-enabled user interface.
myFeature.buildSectionNav() will be called by myFeature.init(). It will take a jQuery object that contains all of the sections from the semantic HTML and use those sections to build the top navigation. It will bind the click handlers to the top navigation items so that clicking on them will show the appropriate section.
myFeature.buildItemNav() will be called by myFeature.showSection(). It will ake a jQuery object that contains all of the items associated with the section from the semantic HTML, and use them to build the side navigation. It will bind the click handlers to the side navigation items so that clicking on them will show the appropriate content.
myFeature.showSection() will be called when the user clicks on an item in the top navigation. It will use the navigation item that’s clicked on to figure out which section to show from the semantic HTML.
myFeature.showContentItem() will be called when the user clicks on an item in the side navigation. It will use the navigation item that’s clicked on to figure out which content item to show from the semantic HTML.
We’ll also make room for a configuration property, myFeature.config, which will be a single location for setting default values rather than scattering them throughout the code. We’ll include the ability to override the defaults when we define the myFeature.init() method.
Once we’ve built this skeleton, it’s time to start coding. Let’s start by setting up a simple myFeature.config object and writing the myFeature.init() method:
'config':{// default container is #myFeature'container':$('#myFeature')},'init':function(config){// provide for custom configuration via init()if(config&&typeof(config)=='object'){$.extend(myFeature.config,config);}// create and/or cache some DOM elements// we'll want to use throughout the codemyFeature.$container=myFeature.config.container;myFeature.$sections=myFeature.$container.// only select immediate children!find('ul.sections > li');myFeature.$section_nav=$('
').attr('id','section_nav').prependTo(myFeature.$container);myFeature.$item_nav=$('
').attr('id','item_nav').insertAfter(myFeature.$section_nav);myFeature.$content=$('
').attr('id','content').insertAfter(myFeature.$item_nav);// build the section-level nav and// "click" the first itemmyFeature.buildSectionNav(myFeature.$sections);myFeature.$section_nav.find('li:first').click();// hide the plain HTML from sightmyFeature.$container.find('ul.sections').hide();// make a note that the initialization// is complete; we don't strictly need this// for this iteration, but it can come in handymyFeature.initialized=true;}
Next we’ll create the myFeature.buildSectionNav() method:
1234567891011121314151617181920212223242526272829
'buildSectionNav':function($sections){// iterate over the provided list of sections$sections.each(function(){// get the sectionvar$section=$(this);// create a list item for the section navigation$('
')// use the text of the first h2// in the section as the text for// the section navigation.text($section.find('h2:first').text())// add the list item to the section navigation.appendTo(myFeature.$section_nav)// use data() to store a reference// to the original section on the// newly-created list item.data('section',$section)// bind the click behavior// to the newly created list itme// so it will show the section.click(myFeature.showSection);});}
Next we’ll create the myFeature.buildItemNav() method:
1234567891011121314151617181920212223242526272829
// iterate over the provided list of items$items.each(function(){// get the itemvar$item=$(this);// create a list item element for the// item navigation$('
')// use the text of the first h3// in the item as the text for the// item navigation.text($item.find('h3:first').text())// add the list item to the item navigation.appendTo(myFeature.$item.nav)// use data to store a reference// to the original item on the// newly created list item.data('item',$item)// bind the click behavior to the// newly created list item so it will// show the content item.click(myFeature.showContentItem);});
Finally, we’ll write the methods for showing sections and content items:
'showSection':function(){// capture the list item that was clicked onvar$li=$(this);// clear out the left nav and content areamyFeature.$item_nav.empty();myFeature.$content.empty();// get the jQuery section object from the orginal HTML,// which we stored using data() during buildSectionNavvar$section=$li.data('section');// mark the clicked list item as current// and remove the current marker from its siblings$li.addClass('current').siblings().removeClass('current');// find all of the items related to the sectionvar$items=$section.find('ul li');// build the item nav for the sectionmyFeature.buildItemNav($items);// "click" on the first list item in the section's item navmyFeature.$item_nav.find('li:first').click();},'showContentItem':function(){var$li=$(this);// mark the clicked list item as current// and revmoe the current marker from its siblings$li.addClass('current').siblings().removeClass('current');// get the jQuery item object from the original HTML,// which we stored using data during buildContentNavvar$item=$li.data('item');// use the item's HTML to populate the content areamyFeature.$content.html($item.html());}
All that’s left to do is to call the myFeature.init() method:
1
$(document).ready(myFeature.init);
Step 4: Changing Requirements
No project is complete without some last-minute change in the requirements, right? Here’s where the object literal approach really shines by making it quick and fairly painless to implement last-minute changes. What if we need to get the content item excerpts via AJAX instead of from the HTML? Assuming the backend is set up to handle it, try this:
varmyFeature={'config':{'container':$('#myFeature'),// configurable function for getting// a URL for loading item content'getItemURL':function($item){return$item.find('a:first').attr('href');}},'init':function(config){// stays the same},'buildSectionNav':function($sections){// stays the same},'buildItemNav':function($items){// stays the same},'showSection':function(){// stays the same},'showContentItem':function(){var$li=$(this);$li.addClass('current').siblings().removeClass('current');var$item=$li.data('item');varurl=myFeature.config.getItemURL($item);// myFeature.$content.html($item.html());myFeature.$content.load(url);}};
Do you need more flexibility? There’s a lot more you can configure (and therefore override) if you really want to make this flexible. For example, you can use myFeature.config to specify how to find and process the title text for each item in the left nav.
varmyFeature={'config':{'container':$('#myFeature'),// specify the default selector// for finding the text to use// for each item in the item nav'itemNavSelector':'h3',// specify a default callback// for "processing" the jQuery object// returned by the itemNavText selector'itemNavProcessor':function($selection){return'Preview of '+$selection.eq(0).text();}},'init':function(config){// stays the same},'buildSectionNav':function($sections){// stays the same},'buildItemNav':function($items){$items.each(function(){var$item=$(this);// use the selector and processor// from the config// to get the text for each item navvarmyText=myFeature.config.itemNavProcessor($item.find(myFeature.config.itemNavSelector));$('
')// use the new variable// as the text for the nav item.text(myText).appendTo(myFeature.$item_nav).data('item',$item).click(myFeature.showContentItem);});},'showSection':function(){// stays the same},'showContentItem':function(){// stays the same}};
Once you’ve added defaults to the config object, you can override them when you call myFeature.init():
Beyond the scope of this article (but also interesting to contemplate and much easier with the object literal pattern) is this: making the back button retrace your path through the tabs using the jQuery history plugin. I leave it as an exercise for the reader.
Conclusion
If you’ve stepped through the code examples in this column, you should have a basic understanding of the object literal pattern and how it might prove useful to you as you develop more complex features and interactions. You also have access to some code that you can use to build on this basic foundation.
I encourage you to give this pattern a try the next time you find yourself writing more than a few lines of JavaScript — it forces you to think through the elements and behaviors that make up a complex feature or interaction. Once you become proficient, it provides a sturdy foundation for extending and reusing your code.
I’m just back from the inaugural North Carolina jQuery Camp at Viget Labs in Durham, N.C., and a couple of people have asked how it went, so I thought I’d write a quick post. I had a whim a few weeks ago to organize the camp; I envisioned an unstructured day where fellow jQuery developers could get together and talk about how they use the library. I figured that since the jQuery Conference had sold out and had a huge waiting list, getting a couple dozen people together on a Saturday in Durham, N.C. wouldn’t be that hard.
We had around 25 people show up to the camp today, from novices to experts, including Scott Gonzalez, a contributor to the jQuery UI library. True to my (utter lack of) vision, it was a very unstructured day, but productive and fun I think. My only experience with unconferences was at BarCamp RDU just a few weeks ago, so it took me a bit to get into full go-with-the-flow mode, but when I didn’t know what to do, I just asked “what do I do now?” and usually someone would tell me.
We started out by writing some topic ideas up on the wall, and quickly had enough to get started. I split off with the novices to give an intro to the library, while the main room dug into the topics that had been suggested, starting with a talk by Scott about stateful plugins. Up next was Brian Landau from Viget, showing off the code for his mapping plugin and giving an overview of ScrewUnit; then, David Eisinger, also of Viget, showed us some simple strategies for improving perceived performance.
Lunch – made possible by the generosity of Rich Orris, FireStream Media, Ignite Social Media, and DesignHammer – was time for informal conversations and demonstrations. Here’s Scott and someone whose name I don’t remember doing some quality whiteboarding:
We came back from lunch with a reprise of my presentation from the jQuery Conference about using objects to organize your code, minus FAST FORWARD but otherwise largely intact. I was grateful to have more than 30 minutes this time, and we ended up having some good conversation about code organization in general.
From there it was on to some great show-and-tell – people are doing excellent things with the library, and doing them with ease – and then Scott wrapped up the day with an overview of jQuery UI. Probably the biggest hit of the day was Scott’s “just one more thing …” moment, when he showed us a whole new API for using the position method as a setter, coming soon to a plugin near you. Lots of oohs and aahs about that one.
I said at the end of the day that this first camp was really just a proof of concept – yes, I can get 25 people to show up to talk about jQuery. I’m hoping to do another jQuery camp in January, perhaps. There are a few things I’d like to do differently next time. For one, I’d like to be a little bit more intentional about having more than one session that’s suitable for beginners – a lot of the presentations were super-interesting, but way over the heads of people just getting started.
Also, there were a number of people who signed up who didn’t make it, which is a shame because I ordered food expecting a larger turnout. I’d asked people to let me know if they couldn’t make it, but alas only a handful did. Next time, I think I’ll charge a token amount to attend – say $10 or so – so people will feel a bit more committed. If they don’t make it, at least their food will be paid for! Charging a few dollars will also help reduce the need for sponsors – not that I don’t love the sponsors, just that it was a bit of work and stress to line them up.
Finally, next time I’d like to be a little bit more intentional about setting up and promoting the event. This time around, I started promoting it before I even had a venue, and shortly after I secured a venue (thank you Viget!) all the slots were filled. Next time around, I might approach that a little bit differently, especially if I can line up a few different venue options.
That’s my report. For more pictures, visit Flickr.


Page Listing
Add
Module
:
All
All
Search:
Search
#
Module
Slug
Title
Runable
Published
Date Created
Last Updated
2
module
slug
title
Runable
published
created
updated


| PostgreSQL 9.0.10 Documentation | ||||
|---|---|---|---|---|
| Prev | Up | Chapter 7. Queries | Next |
LIMIT and OFFSET allow you to retrieve just a portion of the rows that are generated by the rest of the query:
SELECT select_list FROM table_expression [ ORDER BY ... ] [ LIMIT { number | ALL } ] [ OFFSET number ]
If a limit count is given, no more than that many rows will be returned (but possibly less, if the query itself yields less rows). LIMIT ALL is the same as omitting the LIMIT clause.
OFFSET says to skip that many rows before beginning to return rows. OFFSET 0 is the same as omitting the OFFSET clause, and LIMIT NULL is the same as omitting the LIMIT clause. If both OFFSET and LIMIT appear, then OFFSET rows are skipped before starting to count the LIMIT rows that are returned.
When using LIMIT, it is important to use an ORDER BY clause that constrains the result rows into a unique order. Otherwise you will get an unpredictable subset of the query's rows. You might be asking for the tenth through twentieth rows, but tenth through twentieth in what ordering? The ordering is unknown, unless you specified ORDER BY.
The query optimizer takes LIMIT into account when generating query plans, so you are very likely to get different plans (yielding different row orders) depending on what you give for LIMIT and OFFSET. Thus, using different LIMIT/OFFSET values to select different subsets of a query result will give inconsistent results unless you enforce a predictable result ordering with ORDER BY. This is not a bug; it is an inherent consequence of the fact that SQL does not promise to deliver the results of a query in any particular order unless ORDER BY is used to constrain the order.
The rows skipped by an OFFSET clause still have to be computed inside the server; therefore a large OFFSET might be inefficient.


Deleting a comment does not remove it from the site, only prevents your website from showing the text. Click on the remove button to delete the following comment:" %}


Artificial Intelligence enabled Image generation from text
Generating Images from Object Pathway-Generative Adversial Network Model
Select an Object
Analyze


I am a full stack developer who loves to learn! Experience in Ruby, Rails, JavaScript, React, Redux, Git & SQL. Pizza, bagel and puppy enthusiast.
Fullstack web developer with a passion for social impact and innovation. My Environmental Science and Entreipreneurship background led me to work in the Environmental Insurance industry. I soon after discovered insurtech and the Cyber Insurance industry and found it fascinating. I took a leap of faith and applied to coding bootcamps, and could not be happier with my decision.
Aside from programming, I love to be active and try new things.
Some other facts about me:


Click the button below or use the "Send info to HTML" command in the ADD-INS panel.
Send a Message from Fusion 360 here by clicking Fusion Palette Send Command


| Parameter | Required or Optional | Description |
|---|---|---|
| data | Required | The data must be UTF-8 URL-encoded. Note that URLs have a 2K maximum length, so if you want to
encode
more than 2K bytes (minus the other URL characters), you will have to send your data using POST. Maximum character storage capacity:984,all data will be encoded in UTF-8. |
| size | Optional | The size of each box. The minimum value is 1, each box has only one pixel, and then shrink will not be able to scan. The maximum value is 64, each box has 64 pixels. Image size is determined by the data. The default value is 4, is the most common size. |
| ecl | Optional | error_correction_level - QR codes support four levels of error correction to enable recovery of
missing,
misread, or obscured data.
Greater redundancy is achieved at the cost of being able to store less data. Here are the
supported
values:
|


The restaurant manager who speaks with poise and grace to the patron complaining loudly about the wait service. The levelheaded friend you call in your greatest times of need. The compassionate but composed rescue worker who aids victims after a natural catastrophe. The partner who angers rarely, forgives easily, and assumes accountability for their actions. The successful CEO who balances her profession, her family responsibilities, and her personal hobbies with equal measures of calm and confidence.
The restaurant manager who speaks with poise and grace to the patron complaining loudly about the wait service. The levelheaded friend you call in your greatest times of need. The compassionate but composed rescue worker who aids victims after a natural catastrophe. The partner who angers rarely, forgives easily, and assumes accountability for their actions. The successful CEO who balances her profession, her family responsibilities, and her personal hobbies with equal measures of calm and confidence.


Changes¶
Planned for v0.31
- Nested mesh support
- Data inspector GUI
- Line RT analysis tools
v0.30
- Python3 compatibility
- Integration of Kees’ Mie-scattering code (
radmc3dPy.miescat
, meth:radmc3dPy.dustopac.radmc3dDustOpac.computeDustOpacMie) for dust opacity calculation - New package (sphtool) for re-gridding 3D Smoothed Particle Hydrodynamics (SPH) simulations to regular or AMR grids, including some basic visualisation of the SPH simulations
- Possibility for modular module setup (i.e. generation of grids, variables, radiation sources, etc independently of each other) using the new
class
radmc3dModel
. - Functions to plot dust opacities (
radmc3dPy.analyze.plotDustOpac()
), and scattering matrix elements (radmc3dPy.analyze.plotScatmat()
) - New function (
radmc3dPy.dustopac.radmc3dDustOpac.writeOpac()
) to write dust opacities to file - Internal structural changes (splitting the analyze module to smaller modules, for easier maintenance, but all previous functionality of the analyze module is kept intact)
- Numpy’s fromfile() function is now used for reading dust opacities in
radmc3dPy.dustopac.radmc3dDustOpac
, which makes the file reading less sensitive to the presence of empty lines in the file dust opacity files
v0.29
- Octree AMR support (read and write grid and data fields, generate models with an octree grid, see Octree tutorial)
- Plot 2D contour maps of data fields along axis aligned slices showing also the cell boundaries for AMR models (
radmc3dPy.analyze.plotSlice2D()
) - Plot the polarisation direction for full stokes images (
radmc3dPy.image.plotImage()
thanks Kees!) - Read molecular data files (
radmc3dPy.analyze.readMol()
thanks Kees!) - Plot spectrum (
radmc3dPy.analyze.plotSpectrum()
thanks Kees!) - Functions to calculate dust and gas mass in a model (
radmc3dPy.data.radmc3dData.getDustMass()
,radmc3dPy.data.radmc3dData.getGasMass()
) - Updated tutorials for models using an octree AMR grid


Today's Temperature: 30 degrees Celcius
Your browser doesn't support JavaScript or JavaScript support has been disabled.


More than just auto insurance
Your Policy
> Forget UserID/Password?
The GEICO App and site received #1 rankings according to Keynote's 2015 Mobile Insurance Scorecard. Check out what's new with the GEICO App, and download it today.
Privacy
Legal
Careers
Contact Us
Site Map


Unlimited Games. How should Red play 32?
pips Red=146 White=145
(CorrectAnswer= 0/0, ErrorScore= 0)
This position fools many. Clearly the two should be played bar/23*. This gives Red a healthy lead in the race.
The question is how to play the three. Many elect to play 5/2* but that is the wrong idea. If White fans with both checkers Red will have missed his market by a long way but if White rolls a two he will have gone a long way to equalising the position.
Note that Red is stripped on all his outer board points and needs some flexibility. The three should be played 23/20, providing that flexibility. If White rolls a 2 he will have an anchor but a relatively poor position.
Bar/23*, 5/2* tries for a blitz when in fact Red should consolidate his advantage and play for a running or priming game.
I am the first to admit I got this wrong over the board, but I now have a much better understanding of the position. It is largely about making the cube work efficiently and giving White a difficult decision to make.
It is worth playing around with some of White’s next rolls to get a better understanding of the position. You will find that Red’s doubles are more efficient after bar/23*/20.
Bar/23*, 5/2* is an error but not a blunder.
The question is how to play the three. Many elect to play 5/2* but that is the wrong idea. If White fans with both checkers Red will have missed his market by a long way but if White rolls a two he will have gone a long way to equalising the position.
Note that Red is stripped on all his outer board points and needs some flexibility. The three should be played 23/20, providing that flexibility. If White rolls a 2 he will have an anchor but a relatively poor position.
Bar/23*, 5/2* tries for a blitz when in fact Red should consolidate his advantage and play for a running or priming game.
I am the first to admit I got this wrong over the board, but I now have a much better understanding of the position. It is largely about making the cube work efficiently and giving White a difficult decision to make.
It is worth playing around with some of White’s next rolls to get a better understanding of the position. You will find that Red’s doubles are more efficient after bar/23*/20.
Bar/23*, 5/2* is an error but not a blunder.
1. Cubeful 2-ply bar/23*/20 Eq.: +0.853 0.669 0.293 0.010 - 0.331 0.054 0.002 2. Cubeful 2-ply bar/23* 5/2* Eq.: +0.779 (-0.075) 0.662 0.339 0.013 - 0.338 0.062 0.002 3. Cubeful 2-ply bar/23* 13/10 Eq.: +0.759 (-0.094) 0.653 0.307 0.013 - 0.347 0.062 0.002 4. Cubeful 0-ply bar/23* 6/3 Eq.: +0.595 (-0.258) 0.634 0.284 0.013 - 0.366 0.069 0.002 5. Cubeful 0-ply bar/23* 8/5 Eq.: +0.535 (-0.318) 0.618 0.272 0.013 - 0.382 0.070 0.002