Menu Search
Jump to the content X X
Smashing Conf New York

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

Spicing Up Your Website With jQuery Goodness

There comes a point in every website design when you simply want to give the website a little spice to impress the visitor and make it memorable. You want that sexy interaction to capture the user’s attention. In our previous articles, we showed you how to spice up your website with sexy buttons1, practical elements2 and attractive visual effects3.

In this article, we’ll discuss how to seduce your visitors with a little JavaScript action. In our examples, we’ll be using jQuery, a fast and concise JavaScript library that simplifies HTML document traversing, event handling, animation and Ajax interactions for rapid Web development. Ready? Let’s get things rolling!

Ajax Image Uploader Link

Image uploads will be much better after your read this. Guaranteed. By using a bit of jQuery, we can upload images with previews.

How do you upload images now? You select a file and click upload. Simple, right? Except that once you select your image, you can no longer see what was selected. The name of the file is at the end of the input field, and if the input field is short or the file path is deep, you won’t see anything useful. You’ll forget what you selected and have no idea what you’re about to upload.

Now try this variation on uploading an image. We ditch the “Upload” button in favor of a “Save” button and fire the Ajax upload event as soon as a file is selected. The image is processed server-side, and a thumbnail is loaded onto the existing page. Doesn’t that feel so much better? We now have a visual representation (imagine that!) of the image we selected.

Screenshot4

This is particularly useful in larger forms where many fields will be submitted in a single action. It allows the user to review the form before pressing “Save” and see what image (or images) they selected.

How does it work? Here’s the code. You’l need jQuery and the Ajax Upload jQuery plug-in. Link them up, and make sure jQuery is loaded first.

<script src="/js/jquery.min.js" type="text/javascript"></script>
<script src="/js/ajaxupload.js" type="text/javascript"></script>

Here is the JavaScript we will use in its entirety.

$(document).ready(function(){

	var thumb = $('img#thumb');	

	new AjaxUpload('imageUpload', {
		action: $('form#newHotnessForm').attr('action'),
		name: 'image',
		onSubmit: function(file, extension) {
			$('div.preview').addClass('loading');
		},
		onComplete: function(file, response) {
			thumb.load(function(){
				$('div.preview').removeClass('loading');
				thumb.unbind();
			});
			thumb.attr('src', response);
		}
	});
});

Let’s break the code down now and look at what’s really going on. First, we attach the AjaxUpload behavior to our file form element.

new AjaxUpload('imageUpload', {

Next, we specify where to post the Ajax upload. We want to keep all of our URLs in our HTML document, so we pass this URL using the action attribute of our form element.

action: $('form#newHotnessForm').attr('action'),

Set the name of the file form element that will be posted to your server.

name: 'image',

Add a class to your preview div to indicate that the image is uploading. In our case, we are applying a background image to the preview div. We also need to set the image tag to display: none; in the preview div, so that the loading background image is visible, as well as for a more subtle reason explained below.

onSubmit: function(file, extension) {
     $('div.preview').addClass('loading');
},

When the image has been uploaded, we have to do two things:

  • First, we have to set the src attribute of our preview img tag to the new thumb.
  • Secondly, we have to remove the loading class. If we simply execute these things in that order, then we would see an annoying flicker of the old image when the loading class has been removed but the new image has not yet loaded.

We avoid the annoying flicker of the old image by waiting to remove the loading class until after the preview image’s load event fires. We also unbind our listener after it has fired because we want to capture this event only once.

onComplete: function(file, response) {
	thumb.load(function(){
		$('div.preview').removeClass('loading');
		thumb.unbind();
	});

Lastly, we set the source of the preview image to the thumbnail that our server has just created. In this example, the response from the Ajax call is just the thumbnail’s URL as text. You could return it in whatever fancy format you like.

thumb.attr('src', response);
}

If JavaScript-support is disabled in user’s browsers, they will get the good old submit form without the interactive preview. Clean and functional solution, with rich interactions for users with more capable browsers.

Screenshot5

Better Image Uploads6 Link

Want to try out and implement the image uploader yourself? Check out a live demo, the example code and more for this improved way to support image uploads on your website.

Check out the live demo »7

Validation With jQuery Text-Change Event Link

Here’s a pretty common problem: you have a text form to validate client-side. Doing this is easy enough when the form is submitted, but in some cases doing it as the user is typing is best. For example, imagine how annoying Twitter8 would be if you had to submit your tweet before you were told how many characters it was.

Keep in mind, though, that this kind of immediate validation can be overused or abused. Don’t insult the user by congratulating them for every piece of text they enter in a field.

Screenshot9

Implementing this requires that you bind events to the keyup event — and a couple other events if you want to detect text changes on cut-and-paste events. Even if you’re a JavaScript god, having to keep writing this logic over and over again is tedious. We created a text-change event plug-in to help you handle all text-change events.

Detecting the Text (Better Than Twitter) Link

We begin by detecting text in the standard textarea. Look at the shot below: looks like a standard textarea with a disabled “Save” button.

Screenshot10

If you add text to the field, then the “Save” button enables and then disables when no text is in the field. Moderately impressive, right?

Screenshot11

Now, what if you try copying, pasting or cutting text with the shortcut keys? That works as well. What about right-clicking or using the “Edit” menu? Works, too. (By the way, Twitter doesn’t support the click or menu interactions.)

The code behind this is pretty simple. You’ll need to download and link up the textchange plug-in.

<script src="/javascripts/plugins/jquery.textchange.js"></script>

The plug-in adds the hastext and notext events, to which you can bind input and textarea elements.

$('#exhibita').bind('hastext', function () {
  $('#exhibitaButton').removeClass('disabled').attr('disabled', false);
});
	
$('#exhibita').bind('notext', function () {
  $('#exhibitaButton').addClass('disabled').attr('disabled', true);
});

The hastext event fires when the element goes from having no text to having text, and the notext event fires when the element goes from having text to being blank. Looking for more advanced validation? Keep reading.

Detecting Text Change Link

What about detecting text change in the field?

Screenshot12

This is very easy, too. A third textchange event fires whenever the text changes, and it provides you with the previous value.

$('#exhibitb').bind('textchange', function (event, previousText) {
  $('#output').append('

Text changed from <strong>' + previousText + '</strong> to <strong>' + $(this).val() + '</strong> </p>'); });

Twitter-Style Validation Link

Screenshot13

We can implement some simple Twitter-like validation with just a single line and our textchange event.

$('#twitter').bind('textchange', function (event, previousText) {
  $('#charactersLeft').html( 140 - parseInt($(this).val().length) );
});

Ajax Save Link

Screenshot14

With a little more code and setTimeout, we can hook up an Ajax call to save a few seconds once the user stops editing. The Ajax call is just stubbed out here, but you get the idea.

var timeout;
$('#ajaxSave').bind('textchange', function () {
  clearTimeout(timeout);
  $('#ajaxFired').html('Typing...');
    var self = this;
    timeout = setTimeout(function () {
    $('#ajaxFired').html('Saved: ' + $(self).val());
  }, 1000);
});

Validate Text Link

Screenshot15

This may sound contrived, but say you would like to ensure that the two words “companion cube16” are in the emergency intelligence incinerator (i.e. the text field) before allowing the user to continue. No problem:

$('#emergencyIntelligenceIncinerator').bind('textchange', function () {
  if ($(this).val().indexOf('companion cube') !== -1) {
    $('#continue').removeClass('disabled').attr('disabled', false);
  }
});

jQuery Text-Change event can be very useful for web applications that are aiming for a high level of interactivity and visual feedback. You may even want to analyze some of the input and provide helpful clues. For instance, if the user is opening a new ticket in your support area, you may want to present links to possibly related answers in the support forum. Be sure not to analyze every keystroke, though, as it could result in a significant overhead for the back-end. And it is also important to keep in mind that the immediacy of the application should be subtle and should not interrupt user’s interaction.

Screenshot17

Text Change Events18 Link

Don’t fret about complicated validation, text events and edge cases. Check out the live demo and download the plug-in, which makes it a snap to perform a number of functions on text boxes to look for values, changes and more.

Check out the live demo »19

JavaScript Annotation Plug-In Link

Screenshot20

An application that we recently developed (Notable21) allows users to collect user feedback through interactive tools. Most of these tools require the user to annotate an image. We figured that many folks are trying to solve the same problem, so why not create a plug-in that they can use? This is the result. Our plug-in uses jQuery and makes it very simple to add and save image annotations.

To start off, download the JS Annotation Plug-In. To use the plug-in, just link up jQuery (1.2.3 or higher) and our plug-in.

<script src="/javascripts/plugins/jquery.js"></script>
<script src="/javascripts/plugins/jquery.annotate.js"></script>

Meet Nutmeg the Dog. After clicking on a random spot on Nutmeg, you’ll see the black circle appear.

Screenshot22

function blackNote() {
  return $(document.createElement('span')).addClass('black circle note')
}
	
$('#nutmeg').annotatableImage(blackNote);

Here’s how it works: The first parameter to annotatableImage is a function that is implemented by you and that defines the element to be added when you click. In the example above, that function is called blackNote. Simple, right?

How to Save the Annotations? Link

Glad you asked. Use the jQuery selector to grab all the elements that you want to serialize, and call the serializeAnnotations function.

$('#nutmeg span.note').serializeAnnotations();

These values are returned in an array of objects, so you can easily save them with an Ajax call. The response_time variable is the time in milliseconds that the user took to add the annotation after you made the call to annotatableImage.

Screenshot23

Let’s Get Relative Link

In our website feedback tool we needed to show our annotations in different-sized versions of our original image. The full size is just won’t always cut it in the world of good design. To make this easier, we store the x and y positions of our annotations relative to the width and height of the image.

Screenshot24

If you didn’t pass fifth-grade math, don’t worry: our plug-in does all the basic arithmetic for you. Warning: if you change the aspect ratio or crop the image, this will not work properly. Also, be sure to always store x and y as floating-point data types.

$('#smallNutmeg').addAnnotations(blackNote, annotations);

The annotations variable is an array of objects with x and y attributes. It looks exactly like the array returned by the serializeAnnotations function without the response_time attribute. What other attributes might you put in the annotation object? Read on…

Passing Attributes Link

We may want to pass some data to each of our annotations when adding existing annotations. Maybe we have numbered our annotations, or have added special classes or behaviors, whatever.

Screenshot25

The function we pass to annotatableImage accepts a single parameter, which is the annotation object from the array that you passed to addAnnotations. In this example, we added a position attribute, which we will display.

$('#numberedNutmeg').addAnnotations(function(annotation){
  return $(document.createElement('span')).
    addClass('black circle note').html(annotation.position);
},[
    {x: 0.3875, y: 0.3246, position: 4}, 
    {x: 0.57, y: 0.329, position: 2}
  ]
);

Hitting All the Positions Link

When we were annotating Nutmeg, you may have noticed that the annotation was centered at your click position. This may be great for circles and sparkly unicorns, but sometimes we may want to position our annotations differently.

The xPosition and yPosition options allow you to indicate where the annotation is positioned relative to the click. Options are middle (default), left, right and middle (default), top, bottom, respectively.

$('#labeledNutmeg').annotatableImage(function(annotation){
  return $(document.createElement('span')).addClass('set-label');
}, {xPosition: 'left'});

Give Nutmeg some clicks on our demo page to see what we’re talking about. In this example, we are positioning the click on the left side of the annotation.

Warning: make sure to pass the xPosition and yPosition to the serializeAnnotations function if you set these options in annotatableImage. The default behavior is to calculate the x and y values from the middle of the annotation.

Screenshot26

JavaScript Annotations Plug-In27 Link

Start supporting powerful, easily implemented annotations on your website or app with this plug-in. Adding notes, descriptions and more to these annotations is simple.

Check out the live demo »28

Bonus: CSS Grid Builder Link

Screenshot29

In our design process, we have been using a flexible grid framework that lets us rapidly prototype and implement websites. Recently, we’ve created some variant grids for different widths and gutter sizes, so we thought, why not just create grids on the fly with a simple tool?

Please feel free to use the ZURB CSS Grid Builder30 to build and generate source code for a simple, flexible grid framework for variable grid sizes and column numbers. Play around with it — we prefer it to a more full-featured solution such as YUI because it’s lighter and a little more flexible.

Screenshot31

CSS Grid Builder32 Link

Check out the CSS Grid Builder in the playground. You can preview the grid in different-sized browser windows and output a complete CSS framework.

Check out the grid builder »33

(al)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2009/12/02/pushing-your-buttons-with-practical-css3/
  2. 2 https://www.smashingmagazine.com/2009/12/16/stronger-better-faster-design-with-css3/
  3. 3 https://www.smashingmagazine.com/2010/01/25/the-new-hotness-using-css3-visual-effects/
  4. 4 http://www.zurb.com/playground/ajax_upload
  5. 5 http://www.zurb.com/playground/ajax_upload
  6. 6 http://www.zurb.com/playground/ajax_upload
  7. 7 http://www.zurb.com/playground/ajax_upload
  8. 8 http://twitter.com
  9. 9 http://www.zurb.com/playground/jquery-text-change-custom-event
  10. 10 http://www.zurb.com/playground/jquery-text-change-custom-event
  11. 11 http://www.zurb.com/playground/jquery-text-change-custom-event
  12. 12 http://www.zurb.com/playground/jquery-text-change-custom-event
  13. 13 http://www.zurb.com/playground/jquery-text-change-custom-event
  14. 14 http://www.zurb.com/playground/jquery-text-change-custom-event
  15. 15 http://www.zurb.com/playground/jquery-text-change-custom-event
  16. 16 http://en.wikipedia.org/wiki/Portal_(video_game)
  17. 17 http://www.zurb.com/playground/jquery-text-change-custom-event
  18. 18 http://www.zurb.com/playground/jquery-text-change-custom-event
  19. 19 http://www.zurb.com/playground/jquery-text-change-custom-event
  20. 20 http://www.zurb.com/playground/javascript-annotation-plugin
  21. 21 http://www.notableapp.com
  22. 22 http://www.zurb.com/playground/javascript-annotation-plugin
  23. 23 http://www.zurb.com/playground/javascript-annotation-plugin
  24. 24 http://www.zurb.com/playground/javascript-annotation-plugin
  25. 25 http://www.zurb.com/playground/javascript-annotation-plugin
  26. 26 http://www.zurb.com/playground/javascript-annotation-plugin
  27. 27 http://www.zurb.com/playground/javascript-annotation-plugin
  28. 28 http://www.zurb.com/playground/javascript-annotation-plugin
  29. 29 http://www.zurb.com/playground/css-grid-builder
  30. 30 http://www.zurb.com/playground/css-grid-builder
  31. 31 http://www.zurb.com/playground/css-grid-builder
  32. 32 http://www.zurb.com/playground/css-grid-builder
  33. 33 http://www.zurb.com/playground/css-grid-builder
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to top Tweet itShare on Facebook

Advertisement

ZURB is a close-knit team of interaction designers and strategists that help companies design better products & services through consulting, products, education, books, training and events. Since 1998 ZURB has helped over 75+ clients including: Facebook, eBay, NYSE, Yahoo, Zazzle, Playlist, Britney Spears, among others.

  1. 1

    As a Mac user, I am used to just drag files onto the “choose file” button. But in this example, this is not possible. Although pretty much better than the old and busted one.

    0
  2. 2

    Chad R. Smith

    June 15, 2010 5:07 am

    This is why I freaking love Smashing Magazine! You guys offer the best tutorials and real world examples. I used a lot of what I learned in shaping the front end to my API site at http://theeasyapi.com. It’s a free service that lets other developers access API’s easily. I tried to make the interface as simple as possible so other developers can use the service. Great job ZURB providing examples that make sense and almost anyone can follow.

    1
  3. 3

    Such an awesome article. Love the little bits like the companion cube part, and some great inspiration with the captions and things. Awesome!

    -3
  4. 4

    Adeel Imran

    June 15, 2010 5:33 am

    Wow really nice tutorial hats of to you Zurb keep up the great work brilliant guide must say.

    Adeel

    -1
  5. 5

    Good read! I am so happy to see JQ taking that infamous turn from being a code based phenomena to it being integrated in easy to handle, almost code free kits and plug-ins. Soon enough everyone will be doing it and then, after 10 years (give or take) we will throw it out the window and replace it with something better. As I mentioned, so glad to be one step closer to that moment.

    0
  6. 6

    Pete Meyers

    June 15, 2010 5:40 am

    Yes, jQuery is absolutely brilliant and you can do A LOT with it. And the best: coding is really fast and the results are “cross-browser-able”.

    For jQuery in real-life check here: http://www.idonext.com – it’s a web service for task & group management which uses jQuery heavily and feels like a real desktop app.

    0
  7. 7

    JavaScript and especially jQuery is a really easy way to get interaction on websites, as shown by the following (small) showcase of international websites!

    0
  8. 8

    Russell Bishop

    June 15, 2010 6:00 am

    There are some nice examples here for adding jQuery to your website, and some of these examples will definitely create enhanced interaction with your website.

    Then again I feel that you clearly ran out of ideas after all of the textchange parts, most notably because the annotate idea is so very specific. What about things like overlays (preventing opening new windows/tabs or changing the page)? How about lightboxes, enabling the user to stay on the page whilst viewing a larger version of an image? These seemed like obvious enhancements.

    0
  9. 9

    Thomas McGee

    June 15, 2010 6:03 am

    I’ve started implementing jQuery into several Websites lately that I’ve designed. This will definitely come in useful and gives some good ideas. Thanks!

    0
  10. 10

    Nick Jackson

    June 15, 2010 6:25 am

    Great article and some useful jQuery tips. We’ve just started using jQuery on some of our websites – http://www.e-motivemedia.com/category/portfolio. Hopefully we’ll be expanding our jQuery toolkit soon!

    0
  11. 11

    Jquery here, Jquery there…

    I LOVE Mootools!

    0
  12. 12

    Jay Dalisay

    June 15, 2010 6:59 am

    Just what I need! Nice!

    1
  13. 13

    Marcus Tucker

    June 15, 2010 7:15 am

    I’ve noticed a bug in your “textchange” special event – the setup & teardown bind/unbinds don’t match:

    setup: function () {
    a(this).bind(“keyup”, a.event.special.textchange.handler);
    a(this).bind(“cut paste input”, a.event.special.textchange.delayedHandler)
    }, teardown: function () {
    a(this).unbind(“keyup”, a.event.special.textchange.keyuphandler);
    a(this).unbind(“cut”, a.event.special.textchange.cuthandler)

    I think the teardown lines should be:
    a(this).unbind(“keyup”, a.event.special.textchange.handler);
    a(this).unbind(“cut paste input”, a.event.special.textchange.delayedHandler)

    You could also improve your code by using namespaced events (http://docs.jquery.com/Namespaced_Events) to do the same with less code:

    setup: function () {
    a(this).bind(“keyup.hastext”, a.event.special.textchange.handler);
    a(this).bind(“cut.hastext paste.hastext input.hastext”, a.event.special.textchange.delayedHandler);
    }, teardown: function () {
    a(this).unbind(“.hastext”)

    0
  14. 14

    pretty fine site. comes in handy

    0
  15. 15

    Tom Arnfeld

    June 15, 2010 8:35 am

    Great post!
    This is the content I like to see :)

    0
  16. 16

    that’s very goood

    Thanks a lot

    0
  17. 17

    I’ve found so many of your articles interesting, but most entirely from outside sources. While I understand the value of including those sources and pooling ideas and techniques, I have been building a great library of their feeds and will soon have no need to come back to SM if it continues to lack any relevant content of its own.

    1
  18. 18

    Vitaly Friedman (Smashing Editorial)

    June 15, 2010 9:02 am

    Interesting, Adam. Please keep in mind that research for the techniques, tools and resources presented in our posts usually takes 15+ hours. Besides, we do publish original articles. Please just take a look around. Still, good luck. And please let us know when your library is available online.

    0
  19. 19

    Good catch Marcus. I fixed this in the gist and the minified code on the playground page.

    0
  20. 20

    Thanks for the tips!

    OT: rofld @ the dogs eyes. haha

    0

↑ Back to top