jQuery CDN as A Named Module In RequireJS

If you want RequireJS to fetch jQuery from a CDN, you’ll need to tell it to do so using the “paths” config:

require.config({
paths: {
"jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"
}
});

As I understand it, if you want to use the local file fallback code a la html5bp you’re out of luck. For those of you who don’t know, the local file fallback code allows you to load jQuery from your own domain if the CDN version fails to load. It looks like this:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.8.2.min.js"><\/script>')</script>

Arguably, if you’re using jQuery it is likely to be a global requirement rather than a requirement for one or two modules. The same sort of thing with BackboneJS. It might be better to place these global requirements in the HTML for your pages (before the RequireJS script) to save typing ‘jquery’ and ‘backbone’ in all your module definitions.

jQuery plugin to associate label “for” attribute with form controls that have dynamic id’s

For whatever reason, you can’t associate your labels with your form controls implicitly by wrapping both the label text and the control in a <label> element:

<label>
  Email address: <input type="email" name="email" value="" placeholder="you@example.com"/>
</label>

You’ve had to explicitly state the form control you want the label to be associated with:

<label for="email">Email address:</label>
<input id="email" type="email" name="email" value="" placeholder="you@example.com"/>

…but your framework has other ideas, it decides to commandeer your precious “id” attribute and change it from a simple and beautiful “email” into a junky “dnn_ctr1163_RegistrationForm_email”. *cough* DotNetNuke *cough*, but also *cough* Wicket *cough* and probably a whole load of others.

The problem is now that your label is no longer associated with your form control, and there isn’t a simple fix, like, for example, change the for attribute to read “dnn_ctr1163_RegistrationForm_email”, because the numbers in the id change each time you refresh the page. The ID is dynamic, and you are receiving accessibility black stars.

So, luckily I noticed that often the id will change, but the framework will leave your originally intended id somewhere in there. I’ve written a jQuery plugin to look at label for attributes and try to find the form control you intended to associate it with before your server side framework so rudely changed it.

How to use

  1. Download the plugin and add it to your page
  2. Select the labels you want to re-associate and call the function eg. $(‘label’).fuzzyFor();

TODO

The plugin finds matches by looking for input, select and textarea elements in the document and checking to see if the for attribute in your label element appears in the id attribute of the form control. At the moment if more than one match is found, it just uses the first (which is probably good enough for most). However, it should probably do something a bit more clever and use the form control that is closest to the label (I’m reasoning that you normally put your label’s close to your controls).

jQuery plugin to add a CSS class to last-child DOM elements

This has been bugging me for ages. IE < 9 does not support the CSS3 last-child pseudo class. I’ve created a _very_ simple jQuery plugin to add a CSS class “last-child” to the element that is the last child of a DOM element.

It performs this recursively, so it’ll apply the class to the last child of an element as well as to the last child of all it’s children…and so on and so forth.

It’ll perform this on each of the set of matched elements in a jQuery object. So you can have it traverse the whole, of your page by providing a jQuery object with the <body> element in it, or you can pick and choose DOM elements to apply the plugin to for efficiency. For instance, you might only need the "last-child" class to be applied to the last child of an unordered or ordered list:

    $('body').lastChild(); // Applies to all elements attached to the document.body
    $('ul, ol').lastChild(); // Applies to all elements in an unordered or ordered list

By default, the plugin applies the CSS class to a restricted set of DOM element types. You can specify the types of DOM elements to apply the class to by passing an options object to the function. In this way you can also specify the name of the CSS class that will be applied:

    $('ul, ol').lastChild({
        tags:['li'], // Only elements with the tag name 'li' will have the class applied to them
        cssClass:'ie-last-child' // The CSS class name will be 'ie-last-child'
    });

For super shorthand, you can simply pass a string to the lastChild function – which it presumes to be the CSS class you want to use:

    $('ul, ol').lastChild('ie-last-child');

You can download the plugin here.

Note, while I created this plugin to get around my IE problem, it is not built specifically for IE. If you only want IE to receive these classes, you’ll probably want to do something like:

    if($.browser.msie) {
        $('body').lastChild();
    }

…but obviously preferably using Modernizr:

    if($('.ie6, .ie7, .ie8').length) {
        $('body').lastChild();
    }

Enjoy!

Highlight text using jQuery and the HTML5 mark tag

Here’s a jQuery plugin I wrote that’ll add HTML5 <mark> tags around keywords or phrases in an element’s body text.

What is mark?

a run of text in one document marked or highlighted for reference purposes, due to its relevance in another context

http://www.whatwg.org/specs/web-apps/

Usage

Add the script to your page, and then when the DOM is ready, do something like:

    $('body').mark('Lorem ipsum');

The plugin can actually be used to wrap any tag around keywords. Simply pass the tag name you want to use as an option:

    $('body').mark({
      text: 'Lorem ipsum',
      tag:  'span',
      cssClass:  'mark'
    });

The above example will wrap span elements around the words lorem and ipsum. Each span element will have the class ‘mark’. View an example implementation.

TODO

  1. Input sanitation on the text to be marked. Currently the text is dumped straight into a regular expression. It needs to be escaped so that any regular expression meta-characters are interpreted as literals.
  2. Similarly, HTML special characters in the input need to be expanded into their HTML entities.
  3. From what I can see, IE doesn’t like <mark> tags, and seems to automatically self close the opening and closing tags inserted into the DOM. WTF? Can anyone shed any light on this problem? For now, you’re going to have to use a <span> with a CSS class

If you’re interested in contributing, get in touch

Update: Hardware accelerated alternative to jQuery animate() top, left, width, height and opacity CSS properties for iPhone/iPad

Update to my post here – I’ve tweaked the script to use CSS3 transitions on Firefox 4+ and Opera 10.50+ as well as modern webkit based browsers such as Chrome and Safari.

The CSS3 transforms and transitions enhanced carousel can be found here:
freestyle-developments.co.uk/demo/public/portsurf/?css3

…and the normal carousel:
freestyle-developments.co.uk/demo/public/portsurf/

Source code for CSS3 transforms and transitions enhanced carousel

N.B. The normal carousel works in IE7 and IE9 beta, but not in IE8 (it seems IE8 can’t figure out the dimensions of DOM elements properly).

Hardware accelerated alternative to jQuery animate() top, left, width, height and opacity CSS properties for iPhone/iPad

I was recently asked to quote for a proof of concept HTML5 alternative to a flash carousel, specifically to run on iPad. I said I’d do it, but the agency later decided that others had tried to create a HTML5 version and had not been able to create a version that performed well enough for the client. From my point of view they were under the impression I couldn’t do any better. So naturally, I spent a few hours of my spare time proving this wrong, just for the fun of it.

Step 1 was to build a version of the carousel in HTML5. I chose to use the jQuery framework because…well, I felt like it. The fruits of my labour are here:

http://freestyle-developments.co.uk/demo/public/portsurf/

Now, you can view this on any browser. All that is happening is that there are a set of list items absolutely positioned in a container, when you click/touch an item on the left/right jQuery animates the top, left, width, height and opacity CSS values for each item.

Fantastic, but, it feels really sluggish on iPad and iPhone 4. Go on, try it out.

Fair enough, they are resource constrained devices. What to do though? I’ve already used all the tricks I could think of fast loops, select operation caching etc. etc. So what now?

Luckily, in iOS, transitions and animations of the -webkit-transform and opacity properties are performance-enhanced. Sweet! These correspond exactly to the two CSS properties I’m trying to manipulate for each item in my carousel. Implementation was a simple case of swapping out the jQuery animate function, for the css function. Passing in the webkit transition, webkit transform and opacity values in its place.

For example:

items[itemIndex - 3].css({
	opacity:1,
	'-webkit-transform':'translate3d(' + carousel.itemPosition.medium.left.x 
            + 'px, ' + carousel.itemPosition.medium.left.y + 'px, 0) scale(0.5)',
	'-webkit-transition':'opacity 0.4s linear, -webkit-transform 0.4s linear'
});

The webkit transition property is saying “transition these CSS properties from what they were previously to their new values, using these transition parameters (0.4s linear)”. The webkit transform property is saying “move this element to the following coordinates, and scale it by a factor of 0.5″.

Check out the hardware accelerated version on your iPad/iPhone and compare it with the other:

http://freestyle-developments.co.uk/demo/public/portsurf/?ha=1 (Note: webkit only)

Here is a video demonstrating the performance differences those of you without iPads.