<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: libraries</title><link href="http://simonwillison.net/" rel="alternate"/><link href="http://simonwillison.net/tags/libraries.atom" rel="self"/><id>http://simonwillison.net/</id><updated>2025-12-04T23:52:21+00:00</updated><author><name>Simon Willison</name></author><entry><title>Text a community college librarian</title><link href="https://simonwillison.net/2025/Dec/4/text-a-librarian/#atom-tag" rel="alternate"/><published>2025-12-04T23:52:21+00:00</published><updated>2025-12-04T23:52:21+00:00</updated><id>https://simonwillison.net/2025/Dec/4/text-a-librarian/#atom-tag</id><summary type="html">
    &lt;p&gt;I take tap dance evening classes at the &lt;a href="https://collegeofsanmateo.edu/"&gt;College of San Mateo&lt;/a&gt; community college. A neat bonus of this is that I'm now officially a student of that college, which gives me access to their library... including the ability to send text messages to the librarians asking for help with research.&lt;/p&gt;
&lt;p&gt;I recently wrote about &lt;a href="https://www.niche-museums.com/114"&gt;Coutellerie Nontronnaise&lt;/a&gt; on my Niche Museums website, a historic knife manufactory in Nontron, France. They had &lt;a href="https://niche-museums.imgix.net/Coutellerie-Nontronnaise-12.jpeg?w=1200&amp;amp;auto=compress"&gt;a certificate on the wall&lt;/a&gt; claiming that they had previously held a Guinness World Record for the smallest folding knife, but I had been unable to track down any supporting evidence.&lt;/p&gt;
&lt;p&gt;I posed this as a text message challenge to the librarians, and they tracked down &lt;a href="https://archive.org/details/lelivreguinnessd0000na/mode/2up?q=nontronnaise"&gt;the exact page&lt;/a&gt; from the 1989 "Le livre guinness des records" describing the record:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Le plus petit&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Les établissements Nontronnaise ont réalisé un couteau de 10 mm de long, pour le Festival d’Aubigny, Vendée, qui s’est déroulé du 4 au 5 juillet 1987.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thank you, Maria at the CSM library!&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/museums"&gt;museums&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/research"&gt;research&lt;/a&gt;&lt;/p&gt;



</summary><category term="libraries"/><category term="museums"/><category term="research"/></entry><entry><title>AI-generated slop is already in your public library</title><link href="https://simonwillison.net/2025/Feb/5/ai-generated-slop-is-already-in-your-public-library/#atom-tag" rel="alternate"/><published>2025-02-05T01:50:01+00:00</published><updated>2025-02-05T01:50:01+00:00</updated><id>https://simonwillison.net/2025/Feb/5/ai-generated-slop-is-already-in-your-public-library/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.404media.co/ai-generated-slop-is-already-in-your-public-library-3/"&gt;AI-generated slop is already in your public library&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
US libraries that use the &lt;a href="https://www.hoopladigital.com/"&gt;Hoopla&lt;/a&gt; system to offer ebooks to their patrons sign agreements where they pay a license fee for anything selected by one of their members that's in the Hoopla catalog.&lt;/p&gt;
&lt;p&gt;The Hoopla catalog is increasingly filling up with junk AI slop ebooks like "Fatty Liver Diet Cookbook: 2000 Days of Simple and Flavorful Recipes for a Revitalized Liver", which then cost libraries money if someone checks them out.&lt;/p&gt;
&lt;p&gt;Apparently librarians already have a term for this kind of low-quality, low effort content that predates it being written by LLMs: vendor slurry.&lt;/p&gt;
&lt;p&gt;Libraries stand against censorship, making this a difficult issue to address through removing those listings. &lt;/p&gt;
&lt;p&gt;Sarah Lamdan, deputy director of the American Library Association says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If library visitors choose to read AI eBooks, they should do so with the knowledge that the books are AI-generated.&lt;/p&gt;
&lt;/blockquote&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://bsky.app/profile/emilybell.bsky.social/post/3lhenkvj4tt2i"&gt;Emily Bell&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ethics"&gt;ethics&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/slop"&gt;slop&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-ethics"&gt;ai-ethics&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-misuse"&gt;ai-misuse&lt;/a&gt;&lt;/p&gt;



</summary><category term="ethics"/><category term="libraries"/><category term="ai"/><category term="slop"/><category term="ai-ethics"/><category term="ai-misuse"/></entry><entry><title>Introducing Closure Tools</title><link href="https://simonwillison.net/2009/Nov/6/closure/#atom-tag" rel="alternate"/><published>2009-11-06T07:33:56+00:00</published><updated>2009-11-06T07:33:56+00:00</updated><id>https://simonwillison.net/2009/Nov/6/closure/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://googlecode.blogspot.com/2009/11/introducing-closure-tools.html"&gt;Introducing Closure Tools&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Google have released the pure-JavaScript library, apparently used for Gmail, Google Docs and Google Maps. It comes with a powerful JavaScript optimiser tool with linting built in and an accompanying Firebug extension to ensure the obfuscated code it produces can still be debugged. There’s also a template system which precompiles down to JavaScript and can also be called from Java.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/closure"&gt;closure&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/firebug"&gt;firebug&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gmail"&gt;gmail&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/google"&gt;google&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/google-docs"&gt;google-docs&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;&lt;/p&gt;



</summary><category term="closure"/><category term="firebug"/><category term="gmail"/><category term="google"/><category term="google-docs"/><category term="javascript"/><category term="libraries"/></entry><entry><title>YUI 3.0.0: First GA Release of YUI's Next-Generation Codeline</title><link href="https://simonwillison.net/2009/Sep/29/yui/#atom-tag" rel="alternate"/><published>2009-09-29T23:38:18+00:00</published><updated>2009-09-29T23:38:18+00:00</updated><id>https://simonwillison.net/2009/Sep/29/yui/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.yuiblog.com/blog/2009/09/29/yui-3-0-0/"&gt;YUI 3.0.0: First GA Release of YUI&amp;#x27;s Next-Generation Codeline&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
YUI 3 has some very neat ideas—everything is dynamically loaded, so you start with a tiny bootstrap script and call YUI().use(’module-name’) to load just the code you need. Congratulations to the team.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/yahoo"&gt;yahoo&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/yui"&gt;yui&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/yui3"&gt;yui3&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="libraries"/><category term="yahoo"/><category term="yui"/><category term="yui3"/></entry><entry><title>John Resig on Glow</title><link href="https://simonwillison.net/2009/Jul/8/resig/#atom-tag" rel="alternate"/><published>2009-07-08T19:24:19+00:00</published><updated>2009-07-08T19:24:19+00:00</updated><id>https://simonwillison.net/2009/Jul/8/resig/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://news.ycombinator.com/item?id=693971"&gt;John Resig on Glow&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
John criticises Glow for reinventing the wheel—BBC insiders respond in the comments below.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/bbc"&gt;bbc&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/glow"&gt;glow&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/john-resig"&gt;john-resig&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;&lt;/p&gt;



</summary><category term="bbc"/><category term="glow"/><category term="javascript"/><category term="john-resig"/><category term="libraries"/></entry><entry><title>Quoting Dion Almaer</title><link href="https://simonwillison.net/2008/May/27/ajaxian/#atom-tag" rel="alternate"/><published>2008-05-27T17:58:18+00:00</published><updated>2008-05-27T17:58:18+00:00</updated><id>https://simonwillison.net/2008/May/27/ajaxian/#atom-tag</id><summary type="html">
    &lt;blockquote cite="http://ajaxian.com/archives/announcing-ajax-libraries-api-speed-up-your-ajax-apps-with-googles-infrastructure"&gt;&lt;p&gt;If we see good usage, we can work with browser vendors to automatically ship these libraries. Then, if they see the URLs that we use, they could auto load the libraries, even special JIT'd ones, from their local system. Thus, no network hit at all!&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="http://ajaxian.com/archives/announcing-ajax-libraries-api-speed-up-your-ajax-apps-with-googles-infrastructure"&gt;Dion Almaer&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ajax"&gt;ajax&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/browsers"&gt;browsers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/dion-almaer"&gt;dion-almaer&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/google"&gt;google&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;&lt;/p&gt;



</summary><category term="ajax"/><category term="browsers"/><category term="dion-almaer"/><category term="google"/><category term="libraries"/></entry><entry><title>Google AJAX Libraries API</title><link href="https://simonwillison.net/2008/May/27/ajax/#atom-tag" rel="alternate"/><published>2008-05-27T17:56:47+00:00</published><updated>2008-05-27T17:56:47+00:00</updated><id>https://simonwillison.net/2008/May/27/ajax/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://code.google.com/apis/ajaxlibs/"&gt;Google AJAX Libraries API&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Google are hosting copies of jQuery, Prototype, mooTools and Dojo on their CDN, with a promise to permanently host different versions and an optional JavaScript API to dynamically load the most recent version of a library. I wish they’d stop capitalising Ajax though.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="http://ajaxian.com/archives/announcing-ajax-libraries-api-speed-up-your-ajax-apps-with-googles-infrastructure"&gt;Ajaxian&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ajax"&gt;ajax&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/cdn"&gt;cdn&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/dojo"&gt;dojo&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/google"&gt;google&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jquery"&gt;jquery&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mootools"&gt;mootools&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/prototype-js"&gt;prototype-js&lt;/a&gt;&lt;/p&gt;



</summary><category term="ajax"/><category term="cdn"/><category term="dojo"/><category term="google"/><category term="jquery"/><category term="libraries"/><category term="mootools"/><category term="prototype-js"/></entry><entry><title>Doctype: /trunk/goog</title><link href="https://simonwillison.net/2008/May/14/revision/#atom-tag" rel="alternate"/><published>2008-05-14T21:12:07+00:00</published><updated>2008-05-14T21:12:07+00:00</updated><id>https://simonwillison.net/2008/May/14/revision/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://doctype.googlecode.com/svn/trunk/goog/"&gt;Doctype: /trunk/goog&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Google’s newly released JavaScript library (pure JavaScript, so more along the lines of YUI and jQuery than GWT). I haven’t found the documentation for it yet, but the code is extremely well commented. UPDATE: The documentation is spread throughout Doctype.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/dojo"&gt;dojo&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/goog"&gt;goog&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/google"&gt;google&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/googledoctype"&gt;googledoctype&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gwt"&gt;gwt&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jquery"&gt;jquery&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/yui"&gt;yui&lt;/a&gt;&lt;/p&gt;



</summary><category term="dojo"/><category term="goog"/><category term="google"/><category term="googledoctype"/><category term="gwt"/><category term="javascript"/><category term="jquery"/><category term="libraries"/><category term="yui"/></entry><entry><title>querySelector and querySelectorAll</title><link href="https://simonwillison.net/2008/Feb/8/surfinu/#atom-tag" rel="alternate"/><published>2008-02-08T11:21:03+00:00</published><updated>2008-02-08T11:21:03+00:00</updated><id>https://simonwillison.net/2008/Feb/8/surfinu/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://webkit.org/blog/156/queryselector-and-queryselectorall/"&gt;querySelector and querySelectorAll&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
WebKit now supports the W3C Selectors API. Expect the various JavaScript libraries to add this as an optimisation to achieve massive speedups (Prototype are already working on it).


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/prototype-js"&gt;prototype-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/queryselector"&gt;queryselector&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/safari"&gt;safari&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/selectors"&gt;selectors&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/w3c"&gt;w3c&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webkit"&gt;webkit&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="libraries"/><category term="prototype-js"/><category term="queryselector"/><category term="safari"/><category term="selectors"/><category term="w3c"/><category term="webkit"/></entry><entry><title>Low Pro For jQuery?</title><link href="https://simonwillison.net/2008/Feb/3/danwebbnet/#atom-tag" rel="alternate"/><published>2008-02-03T22:16:04+00:00</published><updated>2008-02-03T22:16:04+00:00</updated><id>https://simonwillison.net/2008/Feb/3/danwebbnet/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.danwebb.net/2008/1/31/low-pro-for-jquery"&gt;Low Pro For jQuery?&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Dan Webb on why he prefers Prototype over jQuery: “The one big reason was that, while jQuery was super simple and concise when working on smaller projects, it offered no help in structuring larger applications”.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/dan-webb"&gt;dan-webb&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jquery"&gt;jquery&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/lowpro"&gt;lowpro&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/prototype-js"&gt;prototype-js&lt;/a&gt;&lt;/p&gt;



</summary><category term="dan-webb"/><category term="javascript"/><category term="jquery"/><category term="libraries"/><category term="lowpro"/><category term="prototype-js"/></entry><entry><title>jQuery 1.2.2: 2nd Birthday Present</title><link href="https://simonwillison.net/2008/Jan/15/jquery/#atom-tag" rel="alternate"/><published>2008-01-15T08:59:34+00:00</published><updated>2008-01-15T08:59:34+00:00</updated><id>https://simonwillison.net/2008/Jan/15/jquery/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://jquery.com/blog/2008/01/15/jquery-122-2nd-birthday-present/"&gt;jQuery 1.2.2: 2nd Birthday Present&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
The API stays the same, but there are some healthy speed improvements, a new way of adding custom events and (most importantly) .ready() now waits for the CSS to be ready in addition to the DOM.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/css"&gt;css&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/documentready"&gt;documentready&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/dom"&gt;dom&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jquery"&gt;jquery&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ondomcontentloaded"&gt;ondomcontentloaded&lt;/a&gt;&lt;/p&gt;



</summary><category term="css"/><category term="documentready"/><category term="dom"/><category term="javascript"/><category term="jquery"/><category term="libraries"/><category term="ondomcontentloaded"/></entry><entry><title>YUI 2.4.0 released</title><link href="https://simonwillison.net/2007/Dec/5/yui/#atom-tag" rel="alternate"/><published>2007-12-05T15:32:31+00:00</published><updated>2007-12-05T15:32:31+00:00</updated><id>https://simonwillison.net/2007/Dec/5/yui/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://yuiblog.com/blog/2007/12/04/yuii-240/"&gt;YUI 2.4.0 released&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Lots of great new features, but the one I’m most excited about is Selector: YUI finally has a CSS query engine.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/css"&gt;css&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/selector"&gt;selector&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/yahoo"&gt;yahoo&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/yui"&gt;yui&lt;/a&gt;&lt;/p&gt;



</summary><category term="css"/><category term="javascript"/><category term="libraries"/><category term="selector"/><category term="yahoo"/><category term="yui"/></entry><entry><title>dojo.NodeList API docs</title><link href="https://simonwillison.net/2007/Nov/8/nodelist/#atom-tag" rel="alternate"/><published>2007-11-08T11:16:57+00:00</published><updated>2007-11-08T11:16:57+00:00</updated><id>https://simonwillison.net/2007/Nov/8/nodelist/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://redesign.dojotoolkit.org/?q=jsdoc/dojo/HEAD/object/dojo.NodeList"&gt;dojo.NodeList API docs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Support in Dojo for jQuery-style chaining operations.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/chaining"&gt;chaining&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/dojo"&gt;dojo&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jquery"&gt;jquery&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;&lt;/p&gt;



</summary><category term="chaining"/><category term="dojo"/><category term="javascript"/><category term="jquery"/><category term="libraries"/></entry><entry><title>Upgrading to Prototype 1.6: real world examples</title><link href="https://simonwillison.net/2007/Oct/24/upgrading/#atom-tag" rel="alternate"/><published>2007-10-24T19:19:44+00:00</published><updated>2007-10-24T19:19:44+00:00</updated><id>https://simonwillison.net/2007/Oct/24/upgrading/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://mislav.caboo.se/js/upgrading-to-prototype-1-6-real-world-examples"&gt;Upgrading to Prototype 1.6: real world examples&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I still don’t find Prototype as intuitive as jQuery, but the API improvements between 1.5 and 1.6 are very impressive.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jquery"&gt;jquery&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/prototype-js"&gt;prototype-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/radiantcms"&gt;radiantcms&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="jquery"/><category term="libraries"/><category term="prototype-js"/><category term="radiantcms"/></entry><entry><title>Protoscript</title><link href="https://simonwillison.net/2007/Sep/7/protoscript/#atom-tag" rel="alternate"/><published>2007-09-07T22:55:26+00:00</published><updated>2007-09-07T22:55:26+00:00</updated><id>https://simonwillison.net/2007/Sep/7/protoscript/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://protoscript.com/"&gt;Protoscript&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
JavaScript tool designed for easy prototyping of JS interactions; powered by YUI and jQuery.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="http://looksgoodworkswell.blogspot.com/2007/09/announcing-protoscript.html"&gt;Bill Scott&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/bill-scott"&gt;bill-scott&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jquery"&gt;jquery&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/protoscript"&gt;protoscript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/prototyping"&gt;prototyping&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/yui"&gt;yui&lt;/a&gt;&lt;/p&gt;



</summary><category term="bill-scott"/><category term="javascript"/><category term="jquery"/><category term="libraries"/><category term="protoscript"/><category term="prototyping"/><category term="yui"/></entry><entry><title>Building a JavaScript Library</title><link href="https://simonwillison.net/2007/Aug/24/building/#atom-tag" rel="alternate"/><published>2007-08-24T16:02:59+00:00</published><updated>2007-08-24T16:02:59+00:00</updated><id>https://simonwillison.net/2007/Aug/24/building/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.slideshare.net/jeresig/building-a-javascript-library"&gt;Building a JavaScript Library&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Slides from John Resig’s Google Tech Talk. Some great tips in here, including: make your APIs orthogonal, look for common patterns, keep things extensible and write the documentation yourself.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/api-design"&gt;api-design&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/googletechtalk"&gt;googletechtalk&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/john-resig"&gt;john-resig&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jquery"&gt;jquery&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/slideshare"&gt;slideshare&lt;/a&gt;&lt;/p&gt;



</summary><category term="api-design"/><category term="googletechtalk"/><category term="javascript"/><category term="john-resig"/><category term="jquery"/><category term="libraries"/><category term="slideshare"/></entry><entry><title>jQuery for JavaScript programmers</title><link href="https://simonwillison.net/2007/Aug/15/jquery/#atom-tag" rel="alternate"/><published>2007-08-15T02:27:08+00:00</published><updated>2007-08-15T02:27:08+00:00</updated><id>https://simonwillison.net/2007/Aug/15/jquery/#atom-tag</id><summary type="html">
    &lt;p&gt;When &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; came out back in January 2006, my first impression was that it was a cute hack. Basing everything around CSS selectors was a neat idea (see &lt;a href="http://simonwillison.net/2003/Mar/25/getElementsBySelector/"&gt;getElementsBySelector&lt;/a&gt;) but the chaining stuff looked like a bit of a gimmick and the library as a whole didn't look like it would cover all of the bases. I wrote jQuery off as a passing fad.&lt;/p&gt;

&lt;p&gt;Over the past few months it's become clear to me exactly how wrong I was. jQuery is an exceptionally clever piece of engineering. It neatly encapsulates an extraordinary range of common functionality, and provides a clever plugin API for any functionality not included by default. It takes a core abstraction - that of a selection of DOM elements - and extracts as much mileage out of it as possible. Most importantly, it does so in a way that obeys best practices and plays well with other JavaScript code.&lt;/p&gt;

&lt;p&gt;Most introductions to jQuery focus on designers and inexperienced developers. I'm going to try to explain why jQuery should be of interest to experienced programmers as well.&lt;/p&gt;

&lt;h3&gt;Namespacing&lt;/h3&gt;

&lt;p&gt;The key to writing good, reusable JavaScript is to zealously manage your namespace. JavaScript provides a single global namespace (the window object), and many programmers (and some libraries) add symbols to this with abandon. &lt;a href="http://yuiblog.com/blog/2006/06/01/global-domination/"&gt;Global variables are evil&lt;/a&gt;! Smart developers minimise their number of global objects, using techniques like &lt;a href="http://yuiblog.com/blog/2007/06/12/module-pattern/"&gt;the module pattern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;jQuery introduces just one symbol to the global namespace: the jQuery function/object. Everything else is either a directy property of jQuery or a method of the object returned by calls to the jQuery function.&lt;/p&gt;

&lt;p&gt;What about language enhancements? Most libraries provide some variation of map, filter and strip, functions that are sadly missing from the JavaScript engines that ship with most browsers. Some libraries directly extend JavaScript's built-in String and Array classes, but this can be a risky strategy. &lt;code&gt;String.prototype&lt;/code&gt; and &lt;code&gt;Array.prototype&lt;/code&gt; are themselves global namespaces, and adding properties to them brings the same risk of collisions as being careless with regular globals.&lt;/p&gt;

&lt;p&gt;jQuery provides a number of language enhancement functions, but each one is made available as a property of the jQuery object: &lt;code&gt;jQuery.each&lt;/code&gt;, &lt;code&gt;jQuery.extend&lt;/code&gt;, &lt;code&gt;jQuery.grep&lt;/code&gt;, &lt;code&gt;jQuery.map&lt;/code&gt;, &lt;code&gt;jQuery.merge&lt;/code&gt; and &lt;code&gt;jQuery.trim&lt;/code&gt;. There's no chance of these colliding with someone else's code.&lt;/p&gt;

&lt;h3&gt;The infamous $ function&lt;/h3&gt;

&lt;p&gt;I wasn't being entirely truthful when I said that jQuery was the only global symbol introduced: the &lt;code&gt;$&lt;/code&gt; symbol is also set up as a shortcut for jQuery. Thankfully, this is done in a non-destructive way: if you need your old &lt;code&gt;$&lt;/code&gt; function back (if you are already using code based on Prototype, for example) you can call &lt;code&gt;jQuery.noConflict()&lt;/code&gt; to revert to the old &lt;code&gt;$&lt;/code&gt; function.&lt;/p&gt;

If you want the convenience of the &lt;code&gt;$&lt;/code&gt; function for jQuery without colliding with some other use of the global &lt;code&gt;$&lt;/code&gt; function, the jQuery documentation suggests the following idiom:

&lt;pre&gt;&lt;code class="javascript"&gt;(function($) {
    // Within this block, $ is a reference to jQuery
    // Neat, huh?
})(jQuery);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Attaching everything to the &lt;code&gt;$&lt;/code&gt; symbol was one of the things that made me initially dismiss jQuery as a gimmick. For some reason thinking of it in terms of the jQuery symbol makes everything seem a lot more sensible, even though I'm happy to use the &lt;code&gt;$&lt;/code&gt; shortcut in my own code.&lt;/p&gt;

&lt;h3&gt;Selecting some elements&lt;/h3&gt;

&lt;p&gt;Every jQuery operation starts with selecting one or more nodes from the DOM. jQuery's &lt;a href="http://docs.jquery.com/DOM/Traversing/Selectors"&gt;selection syntax&lt;/a&gt; (really a domain specific language) is an interesting hybrid of CSS 1, 2, bits of CSS 3, some XPath and a few custom extensions as well. I won't describe it in detail here, but here are some useful examples:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;jQuery('div.panel')&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;All divs with class="panel"&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('p#intro')&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;The paragraph with id="intro"&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('div#content a:visible')&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;All visible links inside the div with id="content"&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('input[@name=email]')&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;All input fields with name="email"&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('table.orders tr:odd')&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;"odd" numbered rows in a table with class "orders"&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('a[@href^="http://"]')&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;All external links (links that start with http://)&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('p[a]')&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;All paragraphs that contain one or more links&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Of particular interest from the above are &lt;code&gt;:visible&lt;/code&gt; and &lt;code&gt;:odd&lt;/code&gt;, which are jQuery specific extensions. Also note that the attribute selectors use an @ sign, in common with XPath rather than CSS 2.&lt;/p&gt;

&lt;p&gt;The selection language is extremely rich, and is similar to regular expressions in that time taken to learn it will pay off many times over.&lt;/p&gt;

&lt;h3&gt;Doing stuff with them&lt;/h3&gt;

&lt;p&gt;The object returned by a jQuery selector call is an interesting beast. It represents a collection of DOM elements, and behaves a bit like an array - it has a length property, items can be accessed by index and (most importantly) &lt;a href="http://www.getfirebug.com/"&gt;Firebug&lt;/a&gt; treats it as an array when displaying it in the interactive console. This is a clever illusion; the collection is actually a jQuery object, incorporating a large number of methods which can be used to query, modify and extend the collection of selected elements.&lt;/p&gt;

&lt;p&gt;There are three principle categories of jQuery methods: those that manipulate all of the matched elements, those that return a value from the first matched object, and those that modify the selection itself.&lt;/p&gt;

&lt;p&gt;I won't list all of the methods (see &lt;a href="http://visualjquery.com/"&gt;visualjquery.com&lt;/a&gt; for that), but I'll illustrate with some examples. If you have Firebug you can try these out interactively: use this &lt;a href="javascript:void(function(){var s=document.createElement('script');s.src='http://code.jquery.com/jquery-1.1.2.js';document.getElementsByTagName('head')[0].appendChild(s);}())"&gt;Insert jQuery&lt;/a&gt; bookmarklet first to load the jQuery library in to any page, then paste the code examples in to the Firebug console.&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;jQuery('div#primary').width(300);&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Set the width of div id="primary" to 300 px.&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('p').css('line-height', '1.8em');&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Apply a line-height of 1.8em to all paragraphs.&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('li:odd').css({color: 'white', backgroundColor: 'black'});&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Apply two CSS rules to every other list item; note that the css() function can take an object instead of two strings.&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('a[@href^="http://"]').addClass('external').attr('target', '_blank');&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Add a class of "external" to all external links (those beginning with http://), then add target="_blank" for good measure. This makes use of chaining, described below.&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('blockquote').each(function(el) { alert(jQuery(this).text()) });&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Iterate over every blockquote on the page, and alert its textual content (excluding HTML tags).&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('a').html('Click here!');&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Replace all link text on the page with the insidious "Click here!".&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Here are some examples of methods that read values from the first matched element:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;var width = jQuery('div').width();&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;How wide is the first div on the page?&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;var src = jQuery('img').attr('src');&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;What's the src attribute of the first image on the page?&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;var color = jQuery('h1').css('color');&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;What colour is the first h1?&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;There's a pleasing symmetry at work here: the methods used to set attributes (when passed two arguments, or an object representing multiple settings) can instead be used to read values if called with only one argument. This symmetry is used throughout jQuery, making the API much easier to commit to memory.&lt;/p&gt;

&lt;p&gt;Finally, there are methods that modify the set of selected elements itself. Many of these also provide simpler ways of traversing the DOM:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;jQuery('div').not('[@id]')&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Returns divs that do not have an id attribute.&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('h2').parent()&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Returns all elements that are direct parents of an h2.&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('blockquote').children()&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Returns all elements that are children of a blockquote.&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('p').eq(4).next()&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Find the fifth paragraph on the page, then find the next element (its direct sibling to the right).&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('input:text:first').parents('form')&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Find the form parent of the first input type="text" field on the page. The optional argument to parents() is another selector.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h3&gt;Chaining&lt;/h3&gt;

&lt;p&gt;The jQuery team frequently boast about jQuery's support of chaining, even to the point of declaring that "jQuery is designed to change the way that you write JavaScript" right on the front page. Personally I found this a big turn-off, so I'm happy to say that you can make good use of jQuery while avoiding lengthy chains of methods entirely.&lt;/p&gt;

&lt;p&gt;That said, chaining can be used for some neat tricks. In addition to chaining a bunch of DOM manipulation methods together, you can use jQuery's &lt;code&gt;end()&lt;/code&gt; method to push and pop a stack of the selected element contexts. This is a little hard to explain; essentially, every time you use a method that changes the selected set of elements (such as &lt;code&gt;children()&lt;/code&gt; or &lt;code&gt;filter()&lt;/code&gt;) you can later use &lt;code&gt;end()&lt;/code&gt; to revert back to the previous selection. Jesse Skinner gives a neat example of this in action in his tutorial &lt;a href="http://www-128.ibm.com/developerworks/library/x-ajaxjquery.html"&gt;Simplify Ajax development with jQuery&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;$('form#login')
    // hide all the labels inside the form with the 'optional' class
    .find('label.optional').hide().end()
    // add a red border to any password fields in the form
    .find('input:password').css('border', '1px solid red').end()
    // add a submit handler to the form
    .submit(function(){
        return confirm('Are you sure you want to submit?');
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That whole thing is essentially a one-liner. It selects a form, finds some elements within that form, applies changes to them, reverts the selection back to the original form and assigns a &lt;code&gt;submit()&lt;/code&gt; handler to it.&lt;/p&gt;

&lt;p&gt;It's a cute concept, but you don't have to use it if you don't want to. I'm quite happy splitting my code up with a few self-documenting variable names.&lt;/p&gt;

&lt;h3&gt;DOM manipulation&lt;/h3&gt;

&lt;p&gt;jQuery offers a few smart ways of making large scale manipulations to the DOM. The first is quite surprising: the jQuery function can take a snippet of HTML which it will turn in to a DOM element (it actually looks out for a string that starts with a less than sign):&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;var div = jQuery('&amp;lt;div&amp;gt;Some text&amp;lt;/div&amp;gt;');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can use chaining to add attributes to the div once it has been created:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;var div = jQuery('&amp;lt;div&amp;gt;Some text&amp;lt;/div&amp;gt;').addClass('inserted').attr('id', 'foo');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now append it to the body tag:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;div.appendTo(document.body)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or prepend it to a known location using a selector:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;div.prependTo('div#primary')
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Handling events&lt;/h3&gt;

&lt;p&gt;All JavaScript libraries need an event handling utility and jQuery's is no exception. As with &lt;code&gt;attr()&lt;/code&gt; and &lt;code&gt;css()&lt;/code&gt;, the event methods serve dual purpose: call them with a function to assign an event handler; call them without to simulate that event being triggered:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;jQuery('p').click(function() { jQuery(this).css('background-color', 'red'); });&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Set up paragraphs so that when you click them they turn red.&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;jQuery('p:first').click()&lt;/code&gt;&lt;/dt&gt;
    &lt;dd&gt;Send a fake "click" to the first paragraph on the page.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Similar functions exist for the other browser events - mouseover, keyup and so on. Note that within an event handler the 'this' keyword is set to the element that triggered the event; using &lt;code&gt;jQuery(this)&lt;/code&gt; is a common idiom to enable jQuery methods on that element.&lt;/p&gt;

&lt;p&gt;A couple of event related functions deserve a special mention:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;jQuery('a').hover(function() {
    jQuery(this).css('background-color', 'orange');
}, function() {
    jQuery(this).css('background-color', 'white');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;hover()&lt;/code&gt; is a shortcut for setting up two functions that run onmouseover and onmouseout.&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;jQuery('p').one('click', function() { alert(jQuery(this).html()); });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;one()&lt;/code&gt; sets up an event handler that will be removed after the first time it has been fired. The above example causes all paragraphs to alert their contents once the first time they are clicked.&lt;/p&gt;

&lt;p&gt;jQuery also supports custom events, through the &lt;code&gt;bind()&lt;/code&gt; and &lt;code&gt;trigger()&lt;/code&gt; methods (for which &lt;code&gt;click()&lt;/code&gt; and friends are just shortcuts). Custom events can take arguments, handled using an array passed to &lt;code&gt;trigger()&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;jQuery(document).bind('stuffHappened', function(event, msg) {
    alert('stuff happened: ' + msg);
});
jQuery(document).trigger('stuffHappened', ['Hello!']);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Unobtrusive scripting&lt;/h3&gt;

&lt;p&gt;This is a topic that is very dear to me.  I still believe that the best Web applications are the ones that are still usable with scripting turned off, and that the best way to achieve that is through unobtrusive scripting, with events being assigned to elements after the regular page has been loaded (see &lt;a href="http://onlinetools.org/articles/unobtrusivejavascript/"&gt;Unobtrusive Scripting&lt;/a&gt; and &lt;a href="http://domscripting.com/blog/display/41"&gt;Hijax&lt;/a&gt; for more).&lt;/p&gt;

&lt;p&gt;jQuery has excellent support for this. Firstly, the node selection metaphor is core to both jQuery and unobtrusive scripting as a whole. Secondly, jQuery ships with a solution to &lt;a href="http://peter.michaux.ca/article/553"&gt;the window.onload problem&lt;/a&gt; based on Dean Edwards' work getting a "DOM loaded" event to work cross-browser. You can set a function up to run when the DOM is ready for it like so:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;jQuery(document).ready(function() {
    alert('The DOM is ready!');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Even better, you can shortcut the above by passing your function directly to &lt;code&gt;jQuery()&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;jQuery(function() {
    alert('The DOM is ready!');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;jQuery and Ajax&lt;/h3&gt;

&lt;p&gt;jQuery has the best API for Ajax I've seen in any of the major libraries. The most simple form of an Ajax call looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;jQuery('div#intro').load('/some/fragment.html');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This performs a GET request against &lt;var&gt;/some/fragment.html&lt;/var&gt; and populates div#intro with the returned HTML fragment.&lt;/p&gt;

&lt;p&gt;The first time I saw this, I was unimpressed. It's a neat shortcut, but what if you want to do something more advanced like display an Ajax loading indicator? jQuery exposes custom events (&lt;code&gt;ajaxStart&lt;/code&gt;, &lt;code&gt;ajaxComplete&lt;/code&gt;, &lt;code&gt;ajaxError&lt;/code&gt; and more) for you to hook in this kind of code. It also offers a comprehensive low-level API for more complex Ajax interactions:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;jQuery.get('/some/script.php', {'name': 'Simon'}, function(data) {
    alert('The server said: ' + data);
}); // GET against /some/script.php?name=Simon

jQuery.post('/some/script.php', {'name': 'Simon'}, function(data) {
    alert('The server said: ' + data);
}); // POST to /some/script.php

jQuery.getJSON('/some.json', function(json) {
    alert('JSON rocks: ' + json.foo + ' ' + json.bar);
}); // Retrieves and parses /some.json as JSON

jQuery.getScript('/script.js'); // GET and eval() /script.js
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Plugins&lt;/h3&gt;

&lt;p&gt;Considering the amount of functionality you get out of the box, jQuery is actually pretty small - it comes in at 20KB when minified, even smaller when gzipped. Additional functionality outside the framework is handled using plugins, which can (and do) add brand new methods to the existing jQuery instance object. If you want to be able to run:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;jQuery('p').bounceAroundTheScreenAndTurnGreen();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;jQuery's plugin mechanism provides documented hooks for adding that method to the jQuery system. The ease with which these can be created has attracted an impressive community of plugin authors; the &lt;a href="http://jquery.com/plugins/"&gt;Plugin directory&lt;/a&gt; lists well over 100.&lt;/p&gt;

&lt;p&gt;One really nice touch is that you can add custom selectors in a similar way to custom methods. The &lt;a href="http://jquery.com/plugins/project/moreSelectors"&gt;moreSelectors plugin&lt;/a&gt; adds things like "div:color(red)" to match divs with red text, for example.&lt;/p&gt;

&lt;h3&gt;Leaky abstractions&lt;/h3&gt;

&lt;p&gt;In my new-found respect for jQuery, I've been struggling with one philosophical blocker. For the past few years, I've been advising people to only pick a  JavaScript library if they were willing to read the source code and figure out exactly how it works. My reasoning was based on Joel Spolsky's classic essay &lt;a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html"&gt;The Law of Leaky Abstractions&lt;/a&gt;, which points out that the more complexity your APIs are hiding, the more trouble you'll be in when some of that complexity leaks through. Browsers are the leakiest abstraction of them all, so being able to dig yourself out of a hole when the library fails to cover for you is of paramount importance.&lt;/p&gt;

&lt;p&gt;jQuery uses some really arcane tricks to achieve its functionality - parts of it (like the selector code) are positively terrifying. If understanding exactly how the library works is necessary, jQuery must be a poor choice for the majority of developers. However, the enormous popularity of jQuery combined with a distinct lack of horror stories demonstrates that this is not the case.&lt;/p&gt;

&lt;p&gt;I think I'm going to have to reconsider my advice. The way the library works isn't the issue: it's understanding the underlying issues, and knowing what kind of browser differences there are and what kind of techniques your library is using to fix them. No library can protect you 100% against weird browser behaviour, but as long as you have a grounding in the underlying theory you should be able to figure out if a problem stems from your own code, your library or the underlying implementation.&lt;/p&gt;

&lt;h3&gt;To conclude&lt;/h3&gt;

&lt;p&gt;I hope I've made the case that jQuery isn't &lt;em&gt;just&lt;/em&gt; another library - there are enough interesting ideas in there to teach even the most hardened of JavaScript programmers some new tricks. Even if you don't intend on using it, it's still worth spending some time exploring the jQuery ecosystem.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jquery"&gt;jquery&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/plugins"&gt;plugins&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="javascript"/><category term="jquery"/><category term="libraries"/><category term="plugins"/></entry><entry><title>Quoting Tom Occhino</title><link href="https://simonwillison.net/2007/Jul/8/mootools/#atom-tag" rel="alternate"/><published>2007-07-08T07:29:16+00:00</published><updated>2007-07-08T07:29:16+00:00</updated><id>https://simonwillison.net/2007/Jul/8/mootools/#atom-tag</id><summary type="html">
    &lt;blockquote cite="http://forum.mootools.net/viewtopic.php?id=4195#post-21406"&gt;&lt;p&gt;MooTools is not compatible with any other javascript framework. If you "definitely need to work with prototype" (which you don't, since the frameworks each provide all the functionality you need to use only one or the other) then learn how to do what you want to do in prototype. Otherwise, learn to use MooTools to do all the things you want to do. They simply do not work together, and I promise they never will.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="http://forum.mootools.net/viewtopic.php?id=4195#post-21406"&gt;Tom Occhino&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mootools"&gt;mootools&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/prototype-js"&gt;prototype-js&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="libraries"/><category term="mootools"/><category term="prototype-js"/></entry><entry><title>Dojo 0.9 Update</title><link href="https://simonwillison.net/2007/Apr/29/sitepen/#atom-tag" rel="alternate"/><published>2007-04-29T20:18:13+00:00</published><updated>2007-04-29T20:18:13+00:00</updated><id>https://simonwillison.net/2007/Apr/29/sitepen/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.sitepen.com/blog/2007/04/28/dojo-09-update/"&gt;Dojo 0.9 Update&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Big changes are under way in the Dojo camp.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/alex-russell"&gt;alex-russell&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/dojo"&gt;dojo&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;&lt;/p&gt;



</summary><category term="alex-russell"/><category term="dojo"/><category term="javascript"/><category term="libraries"/></entry><entry><title>Quoting Paul Graham</title><link href="https://simonwillison.net/2007/Apr/7/microsoft/#atom-tag" rel="alternate"/><published>2007-04-07T08:22:55+00:00</published><updated>2007-04-07T08:22:55+00:00</updated><id>https://simonwillison.net/2007/Apr/7/microsoft/#atom-tag</id><summary type="html">
    &lt;blockquote cite="http://www.paulgraham.com/microsoft.html"&gt;&lt;p&gt;Microsoft saw the danger of Javascript and tried to keep it broken for as long as they could. But eventually the open source world won, by producing Javascript libraries that grew over the brokenness of Explorer the way a tree grows over barbed wire.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="http://www.paulgraham.com/microsoft.html"&gt;Paul Graham&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/microsoft"&gt;microsoft&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/paul-graham"&gt;paul-graham&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="libraries"/><category term="microsoft"/><category term="paul-graham"/></entry><entry><title>base2</title><link href="https://simonwillison.net/2007/Mar/23/edwards/#atom-tag" rel="alternate"/><published>2007-03-23T17:59:34+00:00</published><updated>2007-03-23T17:59:34+00:00</updated><id>https://simonwillison.net/2007/Mar/23/edwards/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://dean.edwards.name/weblog/2007/03/yet-another/"&gt;base2&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Dean Edwards’ new JavaScript library which adds useful cross-browser features based on upcoming DOM standards (the Selectors API, DOMContentLoaded, addEventListener and more).


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/addeventlistener"&gt;addeventlistener&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/base2"&gt;base2&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/dean-edwards"&gt;dean-edwards&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/domcontentloaded"&gt;domcontentloaded&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/selectors"&gt;selectors&lt;/a&gt;&lt;/p&gt;



</summary><category term="addeventlistener"/><category term="base2"/><category term="dean-edwards"/><category term="domcontentloaded"/><category term="javascript"/><category term="libraries"/><category term="selectors"/></entry><entry><title>Rules For JavaScript Library Authors</title><link href="https://simonwillison.net/2007/Mar/23/dean/#atom-tag" rel="alternate"/><published>2007-03-23T17:53:11+00:00</published><updated>2007-03-23T17:53:11+00:00</updated><id>https://simonwillison.net/2007/Mar/23/dean/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://dean.edwards.name/weblog/2007/03/rules/"&gt;Rules For JavaScript Library Authors&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
The guiding principles behind Dean Edwards’ base2 library, entirely applicable to every JavaScript developer.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/base2"&gt;base2&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/dean-edwards"&gt;dean-edwards&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;&lt;/p&gt;



</summary><category term="base2"/><category term="dean-edwards"/><category term="javascript"/><category term="libraries"/></entry><entry><title>Notes on JavaScript Libraries</title><link href="https://simonwillison.net/2006/Jun/26/libraries/#atom-tag" rel="alternate"/><published>2006-06-26T15:03:00+00:00</published><updated>2006-06-26T15:03:00+00:00</updated><id>https://simonwillison.net/2006/Jun/26/libraries/#atom-tag</id><summary type="html">
    &lt;p&gt;&lt;a href="http://www.vivabit.com/atmedia2006/"&gt;@media 2006&lt;/a&gt; was a blast. Great talks, great people and some of the highest production values I've ever seen at a conference (check out &lt;a href="http://www.flickr.com/search/?q=atmedia2006+bags"&gt;the bags&lt;/a&gt;!).&lt;/p&gt;

&lt;p&gt;I sat on the &lt;a href="http://www.vivabit.com/atmedia2006/sessions/#dom"&gt;JavaScript Libraries: Friend or Foe?&lt;/a&gt; panel, with PPK, Dan Webb, Stuart Langridge and Cameron Adams chairing. It was my first participation in a panel and I really enjoyed it - I've always liked the Q&amp;amp;A bit of giving talks. JavaScript Libraries are an enormous topic but I felt we did them justice considering the time available. For the record, here are the key points that I wanted to get across:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Large JavaScript applications need some kind of library&lt;/strong&gt; - even if it's one built especially for that application. There are a number of problems in JavaScript (most of them originating with browser incompatibilities) that any moderately complex application will need to deal with - things like normalised event handling, DOM node selection, sane animation or drag and drop. Solve these problems once so you can get on to the interesting task of building the application. If you can find a library that solves them for you so much the better!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The big four.&lt;/strong&gt; &lt;a href="http://dojotoolkit.org/"&gt;Dojo&lt;/a&gt;, &lt;a href="http://mochikit.com/"&gt;MochiKit&lt;/a&gt;, &lt;a href="http://prototype.conio.net/"&gt;Prototype&lt;/a&gt;/&lt;a href="http://script.aculo.us/"&gt;Scriptaculous&lt;/a&gt; and the &lt;a href="http://developer.yahoo.com/yui/"&gt;Yahoo! UI Library&lt;/a&gt; are the top of the pile as far as I'm concerned. They cover the bases effectively and each one offers something interesting that makes it worth studying in its own right. If you plan to evaluate some existing libraries these make an excellent starting point.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leaky abstractions.&lt;/strong&gt; Joel Spolsky's essay &lt;a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html"&gt;The Law of Leaky Abstractions&lt;/a&gt; is my favourite of all of his online articles. It's basic tenet is that abstractions that are designed to save the programmer time inevitably leak, and if they leak at a lower level of abstraction than the programmer is familiar with they prove almost impossible to debug. Paradoxically, the more time saving abstractions you are using the more you actually have to know.&lt;/p&gt;

&lt;p&gt;JavaScript is possibly the leakiest abstraction of them all, thanks to the many different browser environments it runs in. If you rely on a library to abstract away the browser bugs from you you are certain to run in to a bug that you can't fix sooner or later. Don't use libraries as crutches; if you're not prepared to figure out what the library is doing for you you'll end up in a world of pain further down the line.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community and documentation matter.&lt;/strong&gt; As with all open-source software, it's a good idea to get a feel for the amount of community activity around a project before you commit to building on it. The big four all have active communities, which means less bugs, more support and a faster rate of improvement. Likewise, good documentation is invaluable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Libraries should play well with others.&lt;/strong&gt; Reusable code that excludes other code from being reused has severely limited long-term value. In JavaScript, that means that libraries that mess with Object.prototype or pollute global namespaces should be treated with caution. The Prototype library was a major culprit here, but thankfully has cleaned up its act (at least with regards to altering Object.prototype) in recent releases. It's all very well saying that you'll always be using code built with your core language modifications in mind, but you may well change your tune when you try to incorporate Yahoo! or Google Maps and everything breaks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Go with the grain.&lt;/strong&gt; If you take the time to learn it properly, JavaScript is a powerful and surprisingly elegant language. Good JavaScript code takes advantage of its dynamic, functional nature. Libraries that promise to take the pain out of JavaScript by &lt;a href="http://code.google.com/webtoolkit/" title="The Google Web Toolkit"&gt;writing the code for you&lt;/a&gt; probably aren't as smart as they seem.  Abstractions leak.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dan Webb has &lt;a href="http://www.sitepoint.com/article/javascript-library"&gt;a good comparison of the big four&lt;/a&gt; on SitePoint, although he did overlook &lt;a href="http://developer.yahoo.com/yui/animation/"&gt;YUI's Animation library&lt;/a&gt; which I consider a highlight.&lt;/p&gt;

&lt;p&gt;For more accurate coverage of the @media panel itself, take a look at my co-worker Paul Hammond's &lt;a href="http://www.paulhammond.org/2006/06/atmedia2/javascript"&gt;detailed notes&lt;/a&gt;.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/atmedia"&gt;atmedia&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/dojo"&gt;dojo&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/libraries"&gt;libraries&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mochikit"&gt;mochikit&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/prototype-js"&gt;prototype-js&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/speaking"&gt;speaking&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/my-talks"&gt;my-talks&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/yui"&gt;yui&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="atmedia"/><category term="dojo"/><category term="javascript"/><category term="libraries"/><category term="mochikit"/><category term="prototype-js"/><category term="speaking"/><category term="my-talks"/><category term="yui"/></entry></feed>