Our Blog
  • A jQuery Flickr Feed Plugin

    View the Demo | Download the Zip

    We often work with clients that maintain accounts with Twitter, Flickr, Youtube and other services in addition to their website. Often they will want to pull in data from one of their accounts to their website.  With Flickr, this is pretty easy because they make a simple API available.  Having worked with it a few times, we decided to make it even easier to pull photos from a public feed.

    flickr dogs

    There are a few examples of this in use on the demo page.  All of the photos on this page have been used with the generous permission of John Roberts (@jroberts13).

    Plugin Overview

    This plugin works by pulling a JSON feed from Flickr and applying the data it gets back to a template.  For example, we can generate this list of pictures:

    <ul>
    	<li><img alt="Photo Title" src="http://farm4.static.flickr.com..." /></li>
    	<li><img alt="Second Photo Title" src="http://farm4.static.flickr.com..." /></li>
    </ul>
    

    From the following jQuery:

    $('ul').jflickrfeed({
    	limit: 2,
    	qstrings: {
    		id: '44802888@N04'
    	},
    	itemTemplate: '<li><img alt="{{title}}" src="{{image_s}}" /></li>'
    });
    

    The plugin gets the feed from Flickr using AJAX and applies each image it gets back to the provided template.

    The Plugin Options

    There are a number of options available on the plugin, these are the defaults:

    flickrbase: 'http://api.flickr.com/services/feeds/',
    feedapi: 'photos_public.gne',
    limit: 20,
    qstrings: {
    	lang: 'en-us',
    	format: 'json',
    	jsoncallback: '?'
    },
    cleanDescription: true,
    useTemplate: true,
    itemTemplate: '',
    itemCallback: function(){}
    

    Here is a description of each one:

    • flickrbase: This is unlikely to be needed.  It is used to set up the url the jQuery AJAX call will need to be made to.
    • feedapi: There are a number of feeds that flickr makes available.  The default is the public feed.  Here is the list of all that are available: http://www.flickr.com/services/feeds/. This has only been tested on feeds that return photos.  So, for example, don't expect good results using this plugin on the Forum discussion feeds.
    • limit: Set how many items you want to loop through.  Flickr seems to limit its feeds to 20, so that is the default.
    • qstrings: This is the most important setting. This is used to request the correct feed.  In my examples I use this to set the user id.  These are automatically added to the request url. Depending on which feed you use (http://www.flickr.com/services/feeds/) there are different sets of query parameters available: http://www.flickr.com/services/feeds/.
    • cleanDescription: Flickr puts all kinds of junk in the description it returns. By default this plugin is set to remove everything but the plain photo description.
    • useTemplate: Set this to false if you don't want to use the plugins templating system.
    • itemTemplate: The template rules are described below.
    • itemCallback: You can add a callback on each item.  The scope is set to the container and the item object is made available.

    Typically, the only things that will need to be set are limit, qstrings.id and itemTemplate.

    Using the Templates

    In order to make it really easy to use any kind of markup needed with this plugin, a simple templating system has been build in.  Here is an example of a template:

    <li>
    	<a href="{{image_b}}"><img src="{{image_s}}" alt="{{title}}" /></a>
    </li>

    You can see that this is just basic html with a few special tags mixed in.  All of the tags are surrouned by double curly braces. The plugin works by putting in the correct information for each tag and each item into the template.

    The tags that are available depend on what flickr returns for each item.  For the Public Photos API these are: title, link, date_taken, description, published, author, author_id, tags, and image.  For the image property, the plugin uses the Flickr URL scheme to make several sizes available.  You can read about this at http://www.flickr.com/services/api/misc.urls.html.  The image tags available are: image_s, image_t, image_m, image, image_b.

    The Callback Parameter and Integration

    The plugin's second parameter is a callback.  This has the scope of the containing element and has the entire data response available. This is a great feature if you want to integrate this plugin with others.  Let's say you want to integrate it with colorbox. If you call $('selector').colorbox() and then this plugin it won't work.  This is becuase the plugin is adding elements to the page after the colorbox call.  This is even true if you call colorbox after this plugin.  Since this uses ajax, your images won't be added to the page until well after most of your javascript has run.  (In computer time).

    Instead, the trick is to use the callback function.  This allows you to pass in code that you want to run after the images have loaded.  So for example, you can do this:

    $('#cbox').jflickrfeed({
    	limit: 14,
    	qstrings: {
    		id: '37304598@N02'
    	},
    	itemTemplate: '...example...'
    }, function(data) {
    	$('#cbox a').colorbox();
    });
    			

    Now the colorbox call won't be made on the photos until they are loaded.

    Demo and Download

    You can see a demo of this plugin on the demo page.  Additionally you can download a zip of this plugin and the example.

    As always, if you have any questions or comments, leave them below.  Enjoy!

    Categorized in: ,

  • AutoSprites - A jQuery Menu Plugin

    Update 1/22/2009 - This plugin now contains support for an active state. It is just as easy to use and all of the animation still works with it. Read below to see how it works. (This was originally posted 10/28/2009)

    AutoSprites jQuery Menu Plugin

    Download the Files (Zip) | View a Demo

    We have written and released a jquery dropdown menu plugin as well as a CSS Sprites2 Plugin -- this post is along the same lines.  Its purpose is to allow you to build an image-based menu with animated hover states as easily as possible and by using the most concise descriptions possible.  To see the results on both a horizontal and vertical menu, check out the demo.

    Setting up the jQuery Menu Plugin

    The first component when doing something with sprites is a combined image that contains all menu states.  For the menu above, this is the image below was used.  (This was designed by Liaison Design Group, one of our Partners)

    sprites

    The image contains, the normal state, the hover state and the active state. The value to doing things this way is that it allows your site to load faster. Rather than downloading an image for each nav item its hover state and its active state, only a single image needs to be downloaded. This minimizes the overhead of many http requests.

    The next thing to do, is set up the HTML for the nav bar:

    <ul id="hnav"> 
    	<li id="hnavhome"><a href="#">Home</a></li> 
    	<li id="hnavlocal"><a href="#">Local Industry</a></li> 
    	<li id="hnavhigher"><a href="#">Higher Education</a></li> 
    	<li id="hnavcomm"><a href="#">Our Community</a></li> 
    	<li id="hnavnews"><a href="#">News</a></li> 
    
    </ul>
    

    Then we need to set up the CSS. There are a couple of things to note here. We are applying the background image to the containing element so that we don't need to respecify background positioning. This also makes the menu usable if javascript is disabled. Each element needs to have its size defined specifically as well.

    #hnav { position: absolute; top: 0; left: 0; width: 615px; height: 72px; background: url('horiz_sprites.gif') no-repeat; }
    #hnav li { position: absolute; left: 0; height: 72px; }
    	#hnav #hnavhome { width: 82px; left: 0px; }
    	#hnav #hnavlocal { width: 146px; left: 82px; }
    	#hnav #hnavhigher{ width: 162px; left: 228px; }
    	#hnav #hnavcomm { width: 143px; left: 390px; }
    	#hnav #hnavnews { width: 82px; left: 533px; }
    #hnav li a { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 72px; text-indent: -9999em; }
    

    Notice how much less complicated the CSS is than what is typical with sprites. There is no need to define background positioning for each element and its hover state. The last piece you'll need to do is enable the autosprites plugin:

    $(document).ready(function(){
    	$('#hnav').autosprites();
    });
    

    There are no required options. The plugin defaults to a horizontal menu and fading for the animation. It infers everything else from the CSS. If you would like to customize things, here are the options that are available:

    settings = $.extend({
    	offset: '100%',
    	orientation: 'horizontal',
    	over: { opacity: 'show' },
    	overSpeed: 500,
    	out: { opacity: 'hide' },
    	outSpeed: 500,
    	activeState: false,
    	activeClass: 'active',
    	activeSprites: false
    }, settings);
    

    The only bit worth explaining is the active state. In the image above, I show three states. By default, you only need two, a normal state and a hover state. If you set 'activeState' to true, it will use the hover state by default. If you want to specify your own active state, simply set 'activeSprites' to true as well.

    So that's it! You can specify the minimum amount of information about your menu and the sprites will be built automatically. Be sure to check out the demo and download the zip for your own projects. As always leave a comment if you have any complements, insults, suggestions or questions.

    A Special Note on Compiling Javascript

    The purpose of using sprites is to minimize HTTP requests.  It would be foolish to use this plugin by including jQuery, the minimized plugin, and a setup script.  Instead, it is best practice on a production site to bring all of your scripts together into one file, just as sprites bring your images into one file.

    Categorized in: ,

  • Tutorial: A Horizontal jQuery Accordion using Custom Event Binding

    This is the second of two posts about a site we recently launched for a non-profit called Striving for More. This is a great new organization that has started with the goal of improving overall care for young cancer patients. It was a fun and deserving project with a great design:

    Striving for More

    The first post was about how to build a custom jQuery Slideshow on top of some popular jQuery plugins. It covered the required html, css and js needed and it also gave a look into the through process that went into it. This post will take the same approach, but instead look at the custom jQuery horizontal accordion that is on the homepage. Unlike the last project, this one will be build without the help of any plugins. It was created entirely from scratch using jQuery custom events.

    Here is a look at the final product.

    Horizontal jQuery Accordion

    What is it?

    Essentially, this is a horizontal accordion that also changes the text below it on each transition. The one difference between this and a traditional accordion is that when a slide becomes active or inactive, it doesn't just shrink. Instead it slides behind the other slides. Click around on it above to see what I mean.

    The HTML

    The html for this project is really straightforward. There is a group of slides and a group of content:

    <div id="slideshow">
    	<ol id="slides">
    		<li class="slide open" id="slide-[SLIDE NUMBER]">
    			<a href="[SLIDE LINK]">
    				<img src="[SLIDE IMAGE]" alt="" />
    			</a>
    			<a class="slidebutton" href="javascript:void(0);"><img src="[SLIDE BUTTON]" alt="" /></a>
    		</li>
    		...
    	</ol>
    	<ol id="slidecontents">
    		<li class="slidecontent" id="content-slide-[SLIDE NUMBER]">
    			[SLIDE CONTENT]
    		</li>
    		...
    	</ol>
    </div>
    

    The html is in two logical groups, the slide images/navigation and the slide content. These are paired by convention using programatic id attributes. Notice that each of the image slides and the content slides has an id with the [SLIDE NUMBER] in it. This makes the javascript much simpler.

    Ideally the content would be grouped in with the images. This would have made for better markup, as the related items would be put together. This would have required a lot of css positioning trickery since the content wasn't supposed to move with the slide. For the sake of overall simplicity, some html complexity was added.

    The last thing worth noting here is that the slide button text is actually a rendered image. That text can't be rotated reliably in all browsers is really sad. I am confident that this will be accomplished shortly with Canvas. If you're wondering which browsers are the offenders here, you'll probably be surprised. Text can be rotated reliably in EVERY major browser except for Firefox 2.0. It even works in IE. Alas.

    The CSS

    The CSS for this project is probably the simplest part. You'll only notice one little quirk:

    #slides { position: absolute; top: 21px; left: 22px; width: 577px; height: 285px; overflow: hidden; }
    #slides .slide { position: absolute; top: 0px; width: 541px; }
    #slides .slide img { position: absolute; top: 0px; left: 0px; }
    #slides .slide .slidebutton { display: block; position: absolute; top: 0px; right: 0px; height: 285px; width: 21px; background: #693d5e; text-decoration: none; border-right: 1px solid white; }
    #slides .active .slidebutton { background: #55354a; }
    #slides .slide .slidebutton img { position: absolute; top: auto; display: block; bottom: 5px; left: 5px; }
    /* Manually place slides to begin */
    #slide-1 { position: absolute; top: 0; right: 44px; z-index: 3; }
    #slide-2 { position: absolute; top: 0; right: 22px; z-index: 2; }
    #slide-3 { position: absolute; top: 0; right: 0px; z-index: 1; }
    

    It's all straighforward except for that bit at the bottom. I've hardcoded the number of slides. This is typically something I like to avoid, but there were a couple of reasons for it on this project:

    1. I was assured that these slides would be unchanged for quite some time.
    2. At least some CSS Positioning would be required so the page wouldn't look broken while the JS loaded. By being exact there would be no jarring readjustment at all.
    3. It was easier.

    These reasons made the decision obvious. As a quick aside and bonus, here is the css that could be used to rotate the text in CSS. Note that this depends on slightly different markup and it just won't work in Firefox 2.0. So remeber that until FFox2.0 disappears this is useless, though fascinating.

    #slides .slide .slidebutton span 
    { display: block; text-align: right; -webkit-transform: rotate(90deg);  -moz-transform: rotate(90deg);
    						position: absolute; bottom: 100px; left: -90px; width: 200px;
    						color: #f2ecd0; font-family: verdana, sans-serif; font-size: 12px; }
    /* Put the following in your IE stylesheet */
    #slides .slide .slidebutton span { bottom: 190px; left:2px; filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); }
    

    The jQuery

    The jQuery for this little project was the most fun. It ended up being very compact due to the intial positioning of the slides using CSS and because I used custom events.

    What are custom events? In short, they are functions that you can bind to jQuery selectors. This lets you associate actions with the objects that do them, rather than with what triggers them. As an example, you could bind the event 'toggle' to a lightbulb and then trigger it from any number of switches. So if you have multiple switches, they all don't need to keep track of the lightbulb's state. They can just call toggle and the bulb will handle it. (If you like this example, don't credit me. It's borrowed from a great article on jQuery Custom Events written by Rebecca Murphey).

    So here is the entirety of the jQuery code:

    /* Binding Events to the slides */
    $('.slide')
    	.bind('open', function(){
    		if(! $(this).hasClass('open')){
    			$(this).next().trigger('open');
    			$(this).addClass('open');
    			$(this).animate({right: "-=511px"});
    		}
    		else{
    			$(this).prev().trigger('close');
    		}
    		$(this).siblings().removeClass('active');
    		$(this).addClass('active');
    	})
    	.bind('close', function(){
    		if($(this).hasClass('open')){
    			$(this).removeClass('open');
    			$(this).animate({right: "+=511px"});
    			$(this).prev().trigger('close');
    		}
    	});
    		
    /* Binding Events to the Slide Contents */
    $('.slidecontent').bind('show', function(){
    	$('.slidecontent').removeClass('open');
    	$(this).addClass('open');
    });
    
    /* Triggering from the buttons */
    $('.slidebutton').click(function(){
    	$(this).parent().trigger('open');
    	$('#content-' + $(this).parent().attr('id')).trigger('show');
    });
    

    This is certainly terse, so it is worth explaining. I'll start with the events we are binding to '.slide', open and close. To set the stage, remember that each slide is either open (navigation on the right), or closed (navigation on the left). I am keeping track of this by applying an 'open' or 'closed' class to each slide. This is a fairly standard technique.

    Where things might get a bit tricky lie within how an accordion works. The visibile slide isn't the only slide that is open. The slides that come after it must be open as well (their navigation is on the right). So when the second slide is active, the first must be closed and the second and third must be open. This problem gets handled with a little big of recursion.

    The Event Binding

    Let's look at the close event, as it is the simpler of the two. When we close a slide, we first check that it is open. If it is closed, there is nothing to do. If it is open, we close it and then close the slide immediately to its left. This repeats until there isn't a slide to the left or it reaches a slide that has already been closed.

    The open event is only a little more complicated. It works in the exact same way as the close event, except trickles to the right. It also updates which slide is active at each stop along the way.

    Finally you can see how the 'show' event is bound to the slide contents. All this does is remove an open class from every slide content, and then add it back to the one that has been triggered.

    As you can see, a lot of complexity has been encapsulated under these events. This makes it really easy to jump to a particular slide. All that needs to happen is to trigger the 'open' event on the desired slide and the 'show' event on the correct content. This is exactly what the '.slidebutton' code does.

    Putting it all together

    With all of the pieces in place you can see it in action below. Be sure to leave any questions or comments you have about this in our comments below.

    jQuery Horizontal Accordion

    Categorized in: ,

  • Tutorial: A jQuery Slideshow for a Good Cause

    We recently launched a site for a new non-profit called http://www.strivingformore.org" target="_blank">Striving for More. The project was a lot of fun. The site is great-looking, has some cool features, and more importantly it was for a good cause.

    In this post, I am going to cover one of the more important features of the site: an interactive gallery that tells Colleen's Story. I'll breakdown how it was built and the reasons for doing some of the things the way I did. It ends up being very simple and a great example of the power that can be had by combining and tweaking jQuery plugins.

    Here is the final product so you can see where this is headed:

    What is it?

    Colleen's Story is a simple slideshow that can be navigated in any order with an introduction screen. Each slide has a nice navigation button, some narrative and a cool graphic. Because we didn't want the navigation to move around, the content needed to scroll in place, another requirement. For something that looked this good, overflow: auto; wouldn't cut it. After doing some looking around, I decided to use the following plugins for the project:

    • Cycle - This is one of my favorite plugins. If you haven't checked it out you need to. With some improvments that have come in the last 6 months or so it is the only plugin you'll ever need for rotating content. We've rolled our own cycle-like jquery code in the past, but that is rarely necessary. On this project, Cycle will handle all of the slide transitions as well as the navigation.
    • jScrollPane - I'm not generally a fan of replacing the default behavior of browsers, but this situation required it. I played around with serveral plugins before settling on this one which seems to have the fewest downsides.

    The HTML

    To use these plugins will require that we structure our html in a certain way. Here is how it is setup:

    <div id="gallery">
    	<div id="gallery-intro">
    		[Introduction Content]
    		<a href="javascript:void(0);" id="startslides">Begin</a>
    	</div>
    	<div id="gallery-slides" class="hidden">
    		<ol>
    			<li id="slide-[slidenum]">
    				<div class="slide-content">
    					<h2>[Slide Title]</h2>
    					<div class="scroll-content">
    					[Slide Content]
    					</div>
    				</div>
    				<img class="slide-image" src="[Slide Image]" alt="" />
    			</li>
    			...
    		</ol>
    	</div><!-- gallery-slides -->
    	<div id="gallery-nav">
    		<ol>
    			<li id="slide-1-nav">1. Monkey</li>
    			<li id="slide-2-nav">2. Necklace</li>
    			<li id="slide-3-nav">3. IV Beads</li>
    			<li id="slide-4-nav">4. Bag</li>
    			<li id="slide-5-nav">5. Blistex</li>
    			<li id="slide-6-nav">6. Notebook</li>
    			<li id="slide-7-nav">7. Pink Hair</li>
    		</ol>
    	</div><!-- gallery-nav -->
    </div><!-- gallery -->
    

    There are some things to point out here:

    • The Gallery Intro

      Before the slideshow is shown, a description of its purpose is shown. This is grouped independently of the slides. The plan is to make this disappear once the slideshow is started.

    • The group of slides

      All Cycle asks for is a group of slides that are children to one element. In this case it is the ol. We'll end up calling cycle on "#gallery-slides ol". Also notice that I have given this the class "hidden". I do this so that I can hide the slides with css rather than javascript. This is important to do, otherwise while the page loads they will flash.

    • The Navigation

      Cycle provides a navigation (pager) generator. For this project I wanted to have all of my html in one place and give good text descriptions for each slide. Having this dynamicly match the number of slides didn't matter either because these were set in stone. Instead, I just used an id attribute convetion so I could write some simple javascript to link the navigation to the slides.

    • Scroll-Content Class

      I wrapped the content of each slide in a container with the class "scroll-content". This is so that we can target it if necessary using the jScrollPane plugin.

    The CSS

    A concern with this site due to the texture used was download size. While the end result is not perfect, it was taken into consideration when putting this together. The overall strategy was to use one background image for the slideshow frame and let the slide text, images and navigation float over it. One concession was to also include some of the background in the slide images. While this made for some redundant information, the use of jpg compression instead of a 24-bit or even 8-bit png more than made up for it. Finally, sprites were used for the navigation.

    Here is the major layout css:

    /* Container */
    #gallery { position: relative; width: 696px; height: 494px; background: url('gallery-background.jpg'); }
    
    /* Intro Container */
    #gallery-intro { position: absolute; top: 8px; left: 9px; height: 268px; width: 459px; padding: 70px 110px;
    				font: italic 16px Georgia,serif; color: #1e5584; line-height: 32px; text-align: center; }
    #gallery-intro strong { color: #bc9906; display: block; font-weight: normal; }
    #startslides { width: 116px; height: 30px; display: block; margin: 20px auto; background: url('gallery-begin.jpg'); text-indent: -9999em; }
    
    /* Slides */
    #gallery-slides { position: absolute; top: 8px; left: 9px; height: 408px; width: 679px; overflow: hidden; background: transparent; }
    #gallery-slides ol { position: absolute; top: 0; left: 0; list-style: none; margin: 0; padding: 0; width: 679px; height: 408px; background: transparent; }
    #gallery-slides ol li { width: 629px; height: 338px; padding: 25px; }
    
    /* Slide Components */
    #gallery-slides .slide-content { width: 340px; padding-right: 20px; height: 338px; line-height: 18px; z-index: 2; }
    #gallery-slides .scroll-content { overflow: auto; width: 320px; padding-right: 20px; height: 315px; }
    #gallery-slides .slide-content p { margin: 6px 0; }
    #gallery-slides .slide-content h2 { margin: 0px 0 6px 0; font: italic 25px Georgia,serif; color: #bc9906;  }
    #gallery-slides .slide-image { position: absolute; bottom: -25px; right: 1px; z-index: 1; }
    

    The quick things to notice are:

    • The container is positioned relative so that everything else can be placed absolute inside of it.
    • ".scroll-content" has overflow set to auto. This is required for the jScrollPane plugin.

    The navigation was also positioned absolute and set up with a basic CSS sprites technique. You can see the image used here. I am using '.on' in addition to the ':hover' pseudo-class so that we can get the hover states to work in IE6 using javascript. You can get more information on this technique in detail in a classic article on A List Apart. For those of you interested in using the technique for navigation menus, I've also written a plugin to make that dead simple called jQuery AutoSprites.

    #gallery-nav { position: absolute; top: 425px; left: 8px; width: 680px; height: 50px; }
    #gallery-nav ol { position: absolute; margin: 0; padding: 0; top: 0; left: 0; width: 680px; height: 50px; background: url('gallery-sprites.jpg'); }
    #gallery-nav ol li { list-style: none; margin: 0; padding: 0; position: absolute; top: 0; left: 100px; width: 85px; height: 50px; text-indent: -9999em; cursor: pointer; cursor: hand; }
    #gallery-nav ol li.activeslide, #gallery-nav ol li.hov { background-image: url('images/gallery-sprites.jpg'); }
    	#gallery-nav #slide-1-nav { left: 0px; width: 100px; }
    	#gallery-nav #slide-1-nav.activeslide, #gallery-nav #slide-1-nav.hov{ background-position: 0px -50px; }
    	#gallery-nav #slide-2-nav { left: 97px; width: 100px; }
    	#gallery-nav #slide-2-nav.activeslide, #gallery-nav #slide-2-nav.hov { background-position: -97px -50px; }
    	#gallery-nav #slide-3-nav { left: 194px; width: 100px; }
    	#gallery-nav #slide-3-nav.activeslide, #gallery-nav #slide-3-nav.hov { background-position: -194px -50px; }
    	#gallery-nav #slide-4-nav { left: 291px; width: 100px; }
    	#gallery-nav #slide-4-nav.activeslide, #gallery-nav #slide-4-nav.hov { background-position: -291px -50px; }
    	#gallery-nav #slide-5-nav { left: 388px; width: 100px; }
    	#gallery-nav #slide-5-nav.activeslide, #gallery-nav #slide-5-nav.hov{ background-position: -388px -50px; }
    	#gallery-nav #slide-6-nav { left: 485px; width: 100px; }
    	#gallery-nav #slide-6-nav.activeslide, #gallery-nav #slide-6-nav.hov { background-position: -485px -50px; }
    	#gallery-nav #slide-7-nav { left: 582px; width: 100px; }
    	#gallery-nav #slide-7-nav.activeslide, #gallery-nav #slide-7-nav.hov { background-position: -582px -50px; }
    

    The Javascript

    Since our plugins come with quite a bit out of the box it is really simple to get the jQuery running. The first step was to handle the items hidden by css I described above. We can do this right away since the javascript will execute quickly once it gets going as it will be replaced bya jQuery hide.

    $('.hidden').removeClass('hidden');
    $('#gallery-slides').hide();
    

    Next I got the navigation hover states working in IE6 which needs javascript since it doesn't recognize the :hover psuedo-class on non-anchor elements.

    $('#gallery-nav ol li').hover(
    	function(){ $(this).addClass('hov'); },
    	function(){ $(this).removeClass('hov'); }
    );
    

    Next was the simple step of enabling jScrollPane. Don't forget to set these containers as overflow:auto in the css too.

    $('#gallery-slides .scroll-content').jScrollPane({
    	scrollbarWidth: '10'
    });
    

    Setting up a jQuery Cycle is easy, but there was a trick needed for IE. Because I used the fade effect, Cycle sets a background color during the transition to get the text fading to work correctly. I reset this to transparent once the transition is over using the after callback. While this may seem like a pain, little features like this are part of the reason to use established plugins over something homegrown.

    $('#gallery-slides ol').cycle({
    	timeout: 0,
    	fx: 'fade',
    	after: function(){
    		$('#gallery-slides ol li').css('background', 'transparent');
    	}
    });
    

    The last step is adding the custom navigation features. You'll notice that the id of the nav item is used to figure out which slide to show. I also set up the swap between the intro and the slides to occur if either the navigation or "Begin" button is pressed.

    $('#gallery-nav ol li').click(function(){
    	$('#gallery-slides').fadeIn();
    	$('#gallery-intro').fadeOut();
    	$(this).parent().children().removeClass('activeslide');
    	$(this).addClass('activeslide');
    	var slidenum = Number($(this).attr('id').substr(6,1)) - 1;
    	$('#gallery-slides ol').cycle(slidenum);	
    });
    $('#startslides').click(function(){
    	$('#gallery-slides').fadeIn();
    	$('#gallery-intro').fadeOut();
    	$('#slide-1-nav').trigger('click');
    });
    

    Conclusion

    So that's it. Once again you can check out the final product on the Striving for More site. Next week I'll post a tutorial about how the homepage slider was done entirely from scractch. If you want to read about that when it comes out, you should subscribe to the blog.

    Categorized in: ,

  • Use HTML5 form attributes now with nmcFormHelper plugin for jQuery

    Inayaili de León's post last week on 24 ways reminded me about some of the new attributes that HTML5 will be adding to the <input> element. In addition to the flashy new input types (search, color, date, etc.), there are several more mundane, but just as useful, new attributes that can be used on the input types we already have. I created a small jQuery plugin that checks if these attributes are supported natively, and if not it adds support via JavaScript. See an example, or continue reading for the full explanation.

    Placeholder

    A common trick is to set the value of a text input to a short hint about the type of information that should be entered there. Then a couple lines of JavaScript are used to clear that value when the user clicks or tabs into the input. Although there are usability issues with this technique, its convenience is hard to resist. The HTML5 spec includes a new placeholder attribute that creates the same effect without the usability problems.

    To Use:

    <input type="text" name="name" id="name" placeholder="Enter your first and last names" />

    Autofocus

    When the primary purpose of a page is the form—a login page, for instance—it is helpful to start out with the focus on the first input, so the user can just start typing. You can use the new autofocus attribute on the first element to do that. (Be careful, though: setting autofocus on a non-essential form, like a comment form, can be very annoying.)

    To Use:

    <input type="text" name="name" id="name" autofocus="autofocus" />

    Required

    Setting the required attribute prevents the form from submitting unless the input has some value.

    To Use:

    <input type="text" name="name" id="name" required="required" title="This is required" />

    Pattern

    The pattern attribute lets you set a regular expression pattern that must be matched by the input value before the form can be submitted. This is a very powerful tool, allowing for complex validations. Our HiFi RexExp Tool will help you create regular expressions that test for anything from credit card numbers to urls. You should also read the HTML5 spec on the topic, as there are a few caveats. In particular, be aware that the pattern matches the entire value by default, and you should not wrap the expression in forward slashes.

    To Use:

    <!-- Only accept US zip codes -->
    <input type="text" name="zip" id="zip" pattern="(^d{5}$)|(^d{5}-d{4}$)" title="US zip codes only" />

    Using the Plugin

    Some or all of these new attributes are supported by both Safari and Opera. But Firefox and Internet Explorer do not support them natively at this time. To be safe, the nmcFormHelper plugin checks for availability of each attribute (using a technique suggested by Mark Pilgrim) and, if it doesn't exist, uses JavaScript to emulate support.

    At a minumum, you just need to include my script and place a single line in your $(document).ready() block: nmcFormHelper.init();. That will set up all of the new attributes, and you're ready to go.

    Options

    • Placeholder styling: The placeholders are styled to match the native placeholder functionality in Safari. If you wish to set a different style, you can set nmcFormHelper.placeholder.styling = {'color':'red','font-style':'italic'}; or whatever look you choose.
    • Validation functions: The required and pattern attributes will prevent form submission and display an error if the value does not exist or does not match the pattern. By default, a new label will be added after each invalid input, containing the title text of the input. But you can write a function to do anything you want! Just override the functions nmcFormHelper.validation.showErrors and nmcFormHelper.validation.hideErrors (the latter function should undo the former). Both functions will be passed a jQuery object containing all the elements that are affected. Each element will also have one or both of the classes "requiredError" or "patternError" set.

    Bonus!

    Since Internet Explorer does not support CSS attribute selectors, it can be hard to style a text input, for instance, without screwing up your buttons, or vice-versa. So the plugin also adds a class to each of your inputs containing "input-" and the type of the input (i.e. "input-submit"). That way, you can style them individually.

    See an example

    Get the Code

    Full, commented version

    Minified version

    Categorized in: ,

  • Easy menus with nmcDropDown

    nmcDropDown in use on ncbowd.comSince I released my nmcDropDown plugin for jQuery two weeks ago, several people have been asking for a simple example of how to use it. Althought the plugin takes care of all the behavior automatically, you still need to style and format the menu using CSS. In this post I will demonstrate two simple menu styles that use nmcDropDown.

    The bare minimum

    The examples below have styling and effects to make them look nice, but first I will show you the minimum you need to get your menus running. First off, you need a set of nested lists and link to create the structure of your menus:

    <ul id="nav">
      <li><a href="#">Item One</a>
        <ul>
          <li><a href="#">Sub-menu Item 1</a></li>
          <li><a href="#">Sub-menu Item 2</a></li>
          <li><a href="#">Sub-menu Item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item Two</a>
        <ul>
          <li><a href="#">Sub-menu Item 1</a></li>
          <li><a href="#">Sub-menu Item 2</a></li>
          <li><a href="#">Sub-menu Item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item Three</a>
        <ul>
          <li><a href="#">Sub-menu Item 1</a></li>
          <li><a href="#">Sub-menu Item 2</a></li>
          <li><a href="#">Sub-menu Item 3</a></li>
        </ul>
      </li>
    </ul>
    

    Now you need a bit of CSS to put everything in its correct place. This menu isn't going to look nice, but it will give you a starting point from which you can match your site's overall aesthetic.

    #nav { float: right; height: 30px; }
    #nav li { float: left; position: relative; }
    #nav li a { display: block; padding: 5px 10px; line-height: 20px; }
    #nav li ul { display: none; position: absolute; top: 30px; left: 0; width: 120px; background: #fff; }
    #nav li:hover ul { display: block; }
    #nav li ul li { float: none; }
    #nav li ul li a { display: inline-block; }
    #nav li ul li a { display: block; }
    

    The most important thing here is to set #nav li to position: relative; and #nav li ul to position: absolute; to the submenus are aligned with their parent item. In the interest of accessibility, we are also hiding the submenus in the CSS (#nav li ul { display: none; }) and showing them with their parent li is hovered over (#nav li:hover ul { display: block; }. That way, if JavaScript is disabled, the menus will still work in every browser but Internet Explorer 6. JavaScript is always required for drop-downs to work in IE6, unfortunately. Speaking of which, did you notice the oddity at the end where we declare the links as display: inline-block and then re-declare them at display: block? That is the only concession we need to make to Internet Explorer bugs—it removes the extra space IE6 inserts between list items, as discovered by Roger Johansson.

    This CSS will create a horizontal menu with drop-downs, but by changing a few lines, you could just as easily make it a vertical menu with fly-outs.

    Finally, the JavaScript to hook up the nmcDropDown script. Make sure you also paste the nmcDropDown script itself (and the HoverIntent plugin, if you wish to use it) into the JavaScript file.

    $('#nav').nmcDropDown();
    

    Makin' it Pretty

    Screenshot of sample pageNow that we have a functioning menu, we can start styling it. I have created an sample page with two different examples using nmcDropDown.

    The first—in the top-right of the page—is based on the simplified example above, just with additional CSS to style the menu bar and drop-downs. I also added an additional parameter to the call in JavaScript to make the menus slide down instead of fading in: $('#nav').nmcDropDown({show: {height: 'show', opacity: 'show'}});.

    The second example is a little more interesting, as it's actually not a menu at all. In the right-hand sidebar, I am using nmcDropDown to create an informational panel with four heading that, which clicked on, each reveal a bit of text. To do this, I replaced the second level of <ul>s in my HTML with paragraphs. I then used the following CSS to line arrange everything vertically:

    #sidebarNav { padding: 10px 0; background: #ccc; border: 1px solid #bbb; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; }
    #sidebarNav li { border-top: 0 solid #ccc; }
    #sidebarNav li:hover, #sidebarNav li.open { background: #bbb; }
    #sidebarNav li a { display: block; padding: 5px 10px; line-height: 20px; color: #444; font-weight: bold; text-decoration: none; }
    #sidebarNav li p { display: none; padding: 5px 10px 10px; color: #444; border-top: 1px dashed #aaa; }
    #sidebarNav li:hover p { display: block; }
    

    Finally, in the JavaScript I told nmcDropDown to activate on click rather than hover and to look for my paragraph instead of the unordered-list it usually expects:

    $('#sidebarNav').nmcDropDown({
      trigger: 'click',
      submenu_selector: 'p',
      show: {height: 'show'},
      hide: {height: 'hide'}
    });
    

    Please look at the sample page to try these out, and view source to examine the code in more detail. If you find another creative way to use nmcDropDown, please link to it in the comments.

    Categorized in: ,

  • Free Regular Expression Tool for Writing and Testing RegExps

    Regular Expression Editor

    You know the green-on-black code flying all over the computer screens in The Matrix? Regular Expressions don't look too different. They can be really gnarly and debugging them is a pain. This is why we created a free Regular Expression tool to help learn, author, and test RegExps.

    Regular Expressions are a powerful way of programmatically searching for and replacing text. They're used in a wide variety of ways.  Some examples include validating inputs to ensure a user has provided a valid phone number and email address, finding all links to external websites on a web page, extracting content from one website to another, etc.

    I will be using the HiFi RegExp Tool in an upcoming blog post series on "Getting Comfortable with Regular Expressions". You should subscribe to our development blog to receive updates on this series as they come.

    Categorized in: , ,

  • nmcDropDown: A Drop-Down Menu Plugin for jQuery

    ncbowd

    In my post on using template site to save time, I included a quick jQuery plugin for creating drop-down menus. Although that code has served me well I thought it was time to revisit it and make it more flexible and bullet-proof. This is the updated version that I will be including in my blank site template going forward

    I found that I was still having to modify my plugin code to accomodate variations in interaction design. Since I sometimes wanted the menus to only appear whe n the y are clicked—rather than on hover—now that is an option. Also, when the top-level menu items are smaller (or when the sub-menus fly out from the side) the usability can be vastly increased by Brian Cherne's wonderful hoverIntent plugin. HoverIntent keeps the sub-menu from disappearing if your pointer leaves the edge for a split-second. This version will use hoverIntent automatically if you have it; otherwise it will revert to the standard hover event. I recommend copying the minified version of hoverIntent into the bottom of your main JavaScript file. It is quite small and including it in your main file will save an http request and speed up your page loading time.

    Usage

    You should create your navigation as a nested unordered list. Linking the top-level items is optional and will not change the working of the plugin. You should style your menu first with css. How you do that is up to you, but you should set the sub-menus to display: none (this is actually optional, but will prevent the sub-menus from flashing on page-load).

    <ul id="nav">
        <li>About
            <ul>
                <li><a href="#">Profile</a></li>
                <li><a href="#">Board of Directors</a></li>
                <li><a href="#">Contact Info</a></li>
            </ul>
        </li>
        <li><a href="#">Products</a>
            <ul>
                <li><a href="#">Widgets</a></li>
                <li><a href="#">Doohickeys</a></li>
                <li><a href="#">Thing-a-ma-bobs</a></li>
            </ul>
        </li>
    </ul>
    

    The nmcDropDown plugin comes with sensible defaults, so you can just call it on the <ul> element that contains your navigation. The plugin will check each menu item to see if it has a sub-menu and set it up as a drop-down if it does.

    $('#nav').nmcDropDown();

    Configuration

    If you want more control over the way your menu works, there are a number of configuration options available to you. Pass an object containing any that you want to change in as the first parameter of the nmcDropDown() call.

    $('#nav').nmcDropDown({trigger: 'click'});

    Available Options:

    • trigger: Event on which to show or hide the sub-menu, can be 'hover' or 'click'. ('hover')
    • active_class: Class to give open menu items, useful for styling. ('open')
    • submenu_selector: The element immediately below the top-level list-items containing the sub-menu. ('ul')
    • show: Effect(s) to use when showing the sub-menu. ({opacity: 'show'})
    • show_speed: Speed of the show transition. (300)
    • show_delay: Delay before the sub-menu is shown (requires HoverIntent). (50)
    • hide: Effect(s) to use when hiding the sub-menu. ({opacity: 'hide'})
    • hide_speed: Speed of the hide transition. (200)
    • hide_delay: Delay before the sub-menu is hidden (requires HoverIntent). (50)
    • fix_IE: This will attempt to fix IE 6 and 7's problems with z-index, where the sub-menu appears behind the body of the page. Set to false if it is interfering with your other styling. (true)

    Example

    We recently launched a website for North Carolina Business Opportunity and Workforce Development, a program that helps women, minorities, and small businesses secure NCDOT contracts. I created drop-down menus that use the nmcDropDown plugin with custom show and hide animations for an interesting effect. The show animation is {opacity: 'show', top: '-=10px'} (hide is exactly the reverse), which fades the menu in while sliding it up from below.

    Update: I have also created and written up an example of how to use nmcDropDown, including HTML and CSS.

    Download

    Full, commented version (3.5kb)

    Minified version (1.3kb)

    Categorized in: ,

  • Quickly Build and Share a Sitemap with a jQuery Sitemap Creator

    A while back we saw the SlickMap CSS that generated a sitemap from nested unordered lists and we were inspired. Since the DOM is so easy to manipulate using jQuery, why couldn't we build a nice and quick sitemap creator?  With a little bit of free-time hacking, we came up with the HiFi Sitemap Creator.

    HiFi Sitemap Creator

    With this tool it is easy to create and collaborate on a sitemap.   Using the textbox on the left, you can build textile-like nested lists.  This instantly updates the sitemap to the left.  When you click the save button, a custom link is generated for your sitemap.  Share this with a client and they can see and edit the very same sitemap!  They can even make changes and send a link back.

    Additionally, since this is based on CSS it prints beautifully:

    sitemap print

    This was largely based around the Slickmap CSS and jQuery.  Some custom functions were written to translate the textile list to and from html.  This will allow us to add cool features like edit-in-place and drag-and-drop in the future.  For now though, we really like being able to quickly type plain text and see generate a good-looking sitemap.

    We also used the Recess PHP Framework to build a RESTful key-value store for the saved sitemaps.  This took no time at all becuase of the great scaffolding and tools it has out of the box.  It was my first time integrating Recess and jQuery and it couldn't have gone better.

    Check out the final product and be sure to leave comments and suggestions on how to improve it.

    Categorized in: , , ,

  • GetHiFi.com is all Rainbows and Sunshine

    We recently launched a teaser-site for our upcoming CMS, HiFi. It's still a bit premature to be talking about the details of HiFi in this space (sorry!), so instead I want to explain how we implemented the nifty color-changing header.

    GetHiFi.com Landing Page

    Joel deserves most of the credit here, since he came up with the concept and did most of the coding. I just tweaked things for a smoother result.

    The secret to the ever-changing color scheme is an 8000-pixel wide image containing a continuous color gradient. This image is tiled vertically across the header section of the website and overlaid with several other semi-transparent PNGs (IE6? We don't need no stinking IE6) containing the logo, hightlight around the logo, and the dark edges along the top and bottom.

    Gradient

    We are using JavaScript to slowly move the gradient from right to left, exposing a contiuously changing portion of the color spectrum. The script itself is very simple, but it relies on jQuery and the jQuery Background-Position Animation Plugin.

    $(document).ready(function(){
        var initialPos = (Math.floor(Math.random()*8000)+90000) + 'px 0';
    	$('#slider')
    	   .css({backgroundPosition: initialPos})
    	   .animate({backgroundPosition: '(0 0)'}, 1500000, 'linear');
    });
    

    We start by generating a random initial position along the gradient. Actually, we're starting at the end, and moving backwards so the colors fade from right to left. Once we set the starting position, all we need to do is setup a very slow animation of the background position. The animation takes 1500 seconds—25 minutes—and will cycle through the full rainbow twelve times. Since background-images repeat by default, the gradient will wrap around whenever it reaches the end.

    That's all there is to it! Be sure to sign up on GetHiFi.com to receive a notification when we're ready to launch, and follow our blog for more behind-the-scenes information in the mean time.

    Categorized in: ,