Archive for December, 2009

jQuery Content Swapping Portfolio

By Paul Bagosy - December 13th, 2009

jQuery Swapping Portfolio

Here’s a demo of everything I’m about to discuss.

the musical stylings of Eerwyrm will revolt you.

the musical stylings of Eerwyrm will revolt you.

Recently, a number of clients have asked for an complex dynamic image-gallery-like page for a few different applications like portfolios and staff directories. The CMS I work with allows me to build a complex page for the client to load up with content, but the front end is where all the magic happens.

The first of these sites featured an artistic design and required a portfolio for landscape projects, so I wanted to go with an elegant flowing effect. There are two primary element to this concept: the navigation and the content. The content itself can be further divided to images and text, both of which are important elements for this particular layout.

The navigation consits of two columns of thumbnails down the side (or wherever you need them – for this example they’re on the side). They live in a div that’s floated to the right. Here’s what that code looks like:

Each thumbnail is tied to a div which is given a different ID. (link_1, link_2, etc.). In the script, we bind each of those IDs to a click event:

	$('#link_1').bind('click', {id:'1'} ,clickHandler);
	$('#link_2').bind('click', {id:'2'} ,clickHandler);
	etc.

When anything in that div is clicked, it fires the click event, aptly named clickHandler:

	var clickHandler = function(link){
		$('.main').fadeOut().pause(250);
		$('#content').animate({"height": $('#main_' + link.data.id).height() + 20}, {duration: "slow"});
		$('#main_' + link.data.id).pause(250).fadeIn("slow");
	}

Important safety tip: That pause() function is there to slow things down so fadeouts don’t cross:

	$.fn.pause = function(duration) {
	    $(this).animate({ dummy: 1 }, duration);
	    return this;
	};

Now, on the content side, it’s just a matter of stacking up DIVs with your content in them and giving each div a unique (and patterned with the same id structure as your thumbnail IDs) ID (main_1, main_2, etc.). Granted, if you’ve got a lot of data, you’re probably better off with a system to import it via AJAX, but for this instance, we’re going to cover a smaller data set.

So, we’ve got our sidebar:

<div id="sidebar">
 <div id="link_1"><img src="images/thumb_1.jpg" alt="" /></div>
 <div id="link_2"><img src="images/thumb_1.jpg" alt="" /></div>
</div>

And we have our content:

 <div id="content">
  <div id="main_1" class="content_div">Content div 1</div>
  <div id="main_2" class="content_div">Content div 2</div>
 </div>

Now we just need a little styling on the content divs to hide them:

 .content_div { display:none; }

Then it’s just a matter of displaying your first div when the page loads:

	$(window).load(function(){
		$('#content').animate({"height": $('#main_1').height() + 20}, {duration: "slow"});
		$('#main_1').pause(250).fadeIn("slow");
	});

The $(window).load call is important. You don’t want this to fire right on (document).ready if there are any images in your first div, because they will likely not be completely loaded and the code won’t know how big that div is going to be.

so, here’s the simple code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <title></title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <style type="text/css">
   #sidebar { width:230px; float:left; }
   #sidebar div { float:left; margin-left:5px; }
   #content { width:500px; float:left; }
   .content_div { display:none; }
  </style>
  <script language="javascript" type="text/javascript" src="js/jquery.min.js"></script>
  <script language="javascript" type="text/javascript">
   <!--
    $(document).ready(function(){

     $.fn.pause = function(duration) {
      $(this).animate({ dummy: 1 }, duration);
      return this;
     };

     var clickHandler = function(link){
      $('.content_div').fadeOut().pause(250);
      $('#content').animate({"height": $('#main_' + link.data.id).height() + 20}, {duration: "slow"});
      $('#main_' + link.data.id).pause(250).fadeIn("slow");
     }

     $(window).load(function(){
      $('#content').animate({"height": $('#main_1').height() + 20}, {duration: "slow"});
      $('#main_1').pause(250).fadeIn("slow");
     });

     $('#link_1').bind('click', {id:'1'} ,clickHandler);
     $('#link_2').bind('click', {id:'2'} ,clickHandler);
    });
   -->
  </script>
 </head>
 <body id="top">
  <div id="sidebar">
   <div id="link_1"><img src="images/thumbnail.jpg" alt="" /></div>
   <div id="link_2"><img src="images/thumbnail.jpg" alt="" /></div>
  </div>
  <div id="content">
   <div id="main_1" class="content_div">Content div 1</div>
   <div id="main_2" class="content_div">Content div 2</div>
  </div>
 </body>
</html>

Vertically centering images in a DIV

By Paul Bagosy - December 13th, 2009

Have you ever needed to vertically center and image in a div only to realize that it’s nowhere near as easy as it is in a table with vertical-align:middle? Horizontal centering is easy, but that damnable vertical is always just out of reach. Sure, there are ways to make it look centered, but that flies out the window when you’re talking about dynamic sizes.

The work-around I use for this problem is to head a different route. I know I can’t center horizontally with a DIV, so I stop trying and learn to love the space. I just use a blank .gif the same height as my div and then use the style tag right on the IMG to set the background to my image with a position of center center. Viola, instant centered image!

<div style="height:200px; width:200px;"><img src="images/blank.gif" style="background:url(images/thumbnail.jpg) center center no-repeat;" alt="" /></div>
blank Vertically centering images in a DIV

Streamlined graphical navigation

By Paul Bagosy - December 10th, 2009

After covering the long and short of using CSS for mouseover graphical navigation, I was clued into a similar but vastly more efficient way of doing the same thing with less overhead. Why cut up all those images when we can just use one?

Here’s what I’m talking about:

Look familiar?

Look familiar?

Notice the second line of navigation there mirroring the first? That’s all the mouseovers. The trick is simply to position this image as we need it.

So, here’s the HTML:

   <div id="header">
    <ul>
     <li id="nav_01"><a href="http://paul.bagosy.com">Home</a></li>
     <li id="nav_02"><a href="/about/">Home</a></li>
     <li id="nav_03"><a href="/resume/">Resumé</a></li>
     <li id="nav_04"><a href="/portfolio/">Portfolio</a></li>
     <li id="nav_05"><a href="/contact/">Contact</a></li>
     <li id="nav_06"><a href="/feed/">Subscribe to Feed</a></li>
    </ul>
   </div>

Pretty much the same concept as before.

Now, we get into the CSS:

#header                  { width:946px; height:172px; background:url(images/header.jpg) top center no-repeat; position:relative; }
  #header ul             { width:946px; height:172px; margin:0px; padding:0px; list-style:none; }
  #header ul li          { margin:0px; padding:0px; list-style:none; position:absolute; }
  #header ul li a        { text-indent:-9009px; display:block; width:100%; height:100%; }
  #header ul li a:hover  { background-image:url(images/header.jpg); background-repeat:no-repeat; }

What’s important here is that we’re defining the background-image and background-repeat separately in the a:hover declaration, and they’re going to be the same for every link. Granted, you probably don’t need the background-repeat, but it’s good to be thorough.

Now that we’ve defined the overarching styles, let’s do the individual links:

  #nav_01          { width:103px; height:57px; left:45px; top:100px; }
  #nav_01 a:hover  { background-position:-45px -172px; }
  #nav_02          { width:113px; height:57px; left:148px; top:100px; }
  #nav_02 a:hover  { background-position:-148px -172px; }
  #nav_03          { width:122px; height:57px; left:261px; top:100px; }
  #nav_03 a:hover  { background-position:-261px -172px; }
  #nav_04          { width:154px; height:57px; left:383px; top:100px; }
  #nav_04 a:hover  { background-position:-383px -172px; }
  #nav_05          { width:136px; height:57px; left:537px; top:100px; }
  #nav_05 a:hover  { background-position:-537px -172px; }
  #nav_06          { width:227px; height:57px; left:673px; top:100px; }
  #nav_06 a:hover  { background-position:-673px -172px; }

With each of the list items, we’re just telling them how big to be (width, height) and where to be (left, top). We’ve already told the anchor tags to fill their space above, so we just need to worry about the hover. Since we’ve already told them what image to use (the same as the header background), all we need to do is tell them where to put it. We set the background-position to show the mouseover portion of the image by defining it in negative terms (x first, y second).

For this example, we’ve got an image that’s 229 pixels tall, 172 pixels of which will be visible as our header. So, the y part starts at 172 pixels, which means we need to drag it -172 pixels up for each of our mouseovers. Then, it’s as simple as grabbing our left positions for the list item and moving it that far to the left.

Bingo, instant mouseovers with one image. Instead of seven server calls and the need to preload (header BG and six mouseover images), we’re doing one server call and as soon as the header shows, your mouseovers are already preloaded!

Go-Live – PMRS, Inc.

By Paul Bagosy - December 7th, 2009

PMRS Inc.

PMRS, Inc.

PMRS, Inc.

What the client wanted:
A newly-redesigned website to represent their corporate face on the internet. They had concerns about the site being visible in IE6, possibly without JavaScript enabled, due to their target audience using almost exculsively large corporate internet connections with older technology and security restrictions.

What I delivered:
The design itself has a number of floating elements, including Flash and irregularly-repeating backgrounds with alpha-channel elements. PNGs were going to be necessary, and to make sure they worked in IE6, I employed the TwinHelix IE6 PNG hack. This lead me to the horrible realization that positioning background PNGs is problematic in IE6, so there were a few concessions made for IE6 support, but largely, the site looks identical in all browsers.

There was no concern with SEO friendliness, so I went with a JavaScript-based dropdown menu for multi-level support. To compensate for the possibility of a JS being disabled, each top-level menu item has its own landing page, and there is a separate stylesheet loaded with a noscript tag.

Improve the web with Nofollow Reciprocity.