(in parens)

Using Arrays in Templates

14 Dec 2010

Tags: jquery templates arrays

According to the official documentation, .tmpl()’s data parameter…

…can be any JavaScript type, including Array or Object.

The typical case would be to pass an object. This allows you to refer to the properties of that object by name in the template. Demo:

http://gist.github.com/741650

Another typical case would be to pass an object that contains an array of values (not objects). Demo:

http://gist.github.com/741651

The syntax for {{each}} gives the current value an accessible name: $value. That convention does not exist, however, outside of {{each}} and the documentation does not describe the syntax for accessing the current value of an array when the array is the root data item. After looking through the source for the plugin and playing with $item, I found that you can do it as follows. Demo:

http://gist.github.com/741652

$item.data contains the data that the current template is acting on. It refers to the same value throughout a template. It doesn’t, for example, refer to the current item in an {{each}} iteration. Keep in mind, though, that if .tmpl() is called with an array, the template is rendered once for each item in the array, which is why, in the above example, $item.data refers to each individual value, not to the array that was passed in.

Another example requiring the $item.data syntax is when .tmpl() is called with an object, but the object contains an array of values that will be passed to a nested template. Demo:

http://gist.github.com/741654

Short URL

jQuery Templates Plugin

13 Dec 2010

Tags: jquery templates tmpl

Requirements

jQuery Templates is a plugin to jQuery (requiring at least version 1.4.2), so your page will need to reference both jQuery and the templates plugin (in that order).

script type=“text/x-jquery-tmpl”

Templates should be created as the contents of a script tag with any type other than text/javascript. You don’t have to use script tags, but browsers completely ignore script tags if the type is not text/javascript and it’s likely that your template will contain text that would be parsed as invalid HTML (breaking your page), so it’s best if you let the browser ignore it. Note that text/javascript is the default type of a script tag if you don’t specify one, so a type must be specified. It doesn’t matter what type you specify, though I would encourage consistency. You’ll also want to give the script tag an id for easy referencing.

.tmpl([ data ], [ options ])

Both parameters to tmpl() are optional, though I can’t think of a practical example for not passing a data parameter.

data can be any JavaScript type. If data is an array, the template will be rendered once for each item in the array. Otherwise (including if data is missing), the template will be rendered once.

options is an object that contains properties and methods. There is a value named $item that can be accessed in templates. It contains certain properties and methods defined by the plugin, but if options is specified, $item will be extended with options’ properties and methods. That’s all I’ll say about options

Note that since data can be any type, if you want to specify options but not data, you’ll still have to pass something (null, undefined, etc.) in data’s place.

tmpl() returns a jQuery collection of elements so it can be easily passed to any of the jQuery DOM insertion methods (html(), appendTo(), etc.).

Template Tags

jQuery Templates includes a few tags for rendering data. Among others, it includes ${}, {{if}} / {{else}}, and {{each}}.

${}

The ${} tag is used for rendering content from the data passed to the template. ${} has no closing tag. If the template is currently rendering an object (let’s call it user), then ${name} would render the value of user.name, ${emailAddress} would render the value of user.emailAddress, and so on. If the template is currently rendering a value, ${$value} would render the value.

{{if}} / {{else}}

The {{if}} tag requires a closing {{/if}} tag. {{if}} takes a parameter that is the expression to evaluate in the form of {{if expression}}. {{else}} does not have a closing tag. The closing {{/if}} or a new {{else}} closes the previous {{else}}. {{else}} can be given an optional expression parameter which will make it behave like else if.

{{each}}

The {{each}} tag is used for iterating over an array. It has a closing {{/each}} tag. Everything between the two is rendered once for each item in the array. {{each}} takes the array to be iterated as a parameter. If the array is called items, it would be passed as {{each items}}.

Within the {{each}} tag, $value and $index refer to the current value and the index of the current value, respectively. There is optional syntax that allows you to rename $index and $value:

http://gist.github.com/738697

Altogether Now

The code below can be viewed here.

http://gist.github.com/738695

Short URL

jQuery Plugin Pattern

7 Nov 2010

Tags: javascript jquery plugin

This post is a followup to a previous post, JavaScript Module Pattern. jQuery’s documentation encourages developers to use JavaScript’s module pattern to create jQuery plugins. See the previous post if you’re unfamiliar with the module pattern. jQuery itself is passed to the function as its module parameter, typically as $. Plugins are defined within the module function by declaring functions on the $ or $.fn objects. Functions declared on $ are selector-independent and can return whatever the developer chooses. Functions declared on $.fn are selector-dependent and should return a jQuery object to maintain jQuery’s chainability.

As an example, here’s a plugin that provides enable and disable functionality for form controls:

http://gist.github.com/667219

By creating closure around $, the plugin can refer to jQuery using $, even if scripts previously loaded in the page overwrote $ for some reason. It also won’t overwrite that other developer’s $ object. You’re protected from their $ and vice versa.

Within the functions, this will refer to the jQuery object on which the function was invoked.

The two plugin functions take advantage of jQuery’s each function to iterate the set of selected elements, operate on each one in turn, then return the elements to maintain jQuery’s chainability.

Notice in disable that within the each call, only elements that match the ‘:input’ criteria are disabled. I could have saved a couple lines of code and done the filtering by chaining it to the each call:

http://gist.github.com/667221

But then only the matching elements would have been returned by disable. Sometimes you want your plugin to filter elements and only return certain ones. This is not one of those cases. Be mindful that the set of elements you want your plugin to operate on and the set of elements it should return aren’t necessarily the same.

Short URL

Embedding GitHub Gists in Tumblr Posts

20 Oct 2010

Tags: github gist tumblr javascript jquery

Tumblr’s utter lack of Gist support was pretty much a show-stopper for me, which is why this is my first post. In trying to figure out how to hack it myself, I ran across Jarred Grippe’s post describing how he hacked it. I refactored his solution a bit to add some error checking and a couple of features:

http://gist.github.com/637764

Most of the magic comes from the call to embedNextGist inside the document.write overrides. Typically when scripts are being added to the page programatically, you have to be careful not to execute code that depends on the script before the script is loaded. For example, if I had instead just put embedNextGist in a loop, all of the document.write overrides and appending of script tags would have happened long before the first appended script even loaded. The calls to the overridden document.write do not occur until the script has loaded, which would mean that all of the appended scripts would use whichever version of document.write was provided in the last iteration of the loop. That is, each Gist would, in turn, write itself into the last p.gist.

But in this case, all of that trouble is circumvented by calling embedNextGist from document.write which is called by the appended script (a call which, naturally, cannot happen until the script is loaded).

Two other small notes:

  • Jarred’s version writes the stylesheet link for every Gist that it handles. My version never writes the stylesheet link because I have that link as part of my Tumblr template.
  • My version caches document.write before processing Gists and restores it upon completion.

Here is an uncommented version and a 412 byte minified version.

Short URL