Pinwheel jQuery Expanding Box Menu

Jan 3, 02:59 PM

Pinwheel: Paper Waste No Longer

After many revisions and lots of debugging, the final touches on the Pinwheel design and development processes have been rounded off.

expanding boxes

My favorite feature of the Pinwheel site is the jQuery interactive expanding box menu. The selected box expands when the 'Read More' link is clicked, and the other boxes are neatly collapsed. Using jQuery to traverse the DOM tree, the app uses only one function to achieve this effect. Below is an image of the expanding boxes in its default state.

jQuery Animated Div Here it is after 'Read more...' is click on the left box. jQuery Animated Div

Necessary Libraries and Plugins

  • jQuery
  • jQuery UI - I wanted to use jQuery UI's 'switchClass' function because it combines jQuery's 'addClass' and 'animate' into one function. It is easier to manage and prevents visual rendering errors.
  • jQuery Timers - I am using the timer plugin to help prevent multiple clicking errors. If you are feeling mischievous it is still possible to break this example by clicking the anchor rapidly.

Other Plugins

  • Superfish jQuery Menu - not required for expanding boxes but the drop-down menu at the top of the page. Very useful plugin.
  • hoverIntent - this is included with the Superfish package, but I thought I would point in out. Prevents mouse hovering errors.

Download Source Files

html

In fig. 1 below I have illustrated the underlying structure of the expanding boxes' default state. Within box-row are 3 instances of box-container, each exactly the same except for the content paragraphs inside.

default div structure

html of box-container

Within each box-container there are 3 divs floating left of each other. The first div left-left has the left rounded corner of the box as a background image. The middle div mid-mid holds the content paragraphs. The rightmost div left-right has the right rounded corner of the box as a background image.

<div class="box-container">
  <div class="left-left"> </div>
  <div class="mid-mid">
    <p class="left-para">
      <img src="graphics/educational.jpg" height="49" width="225" alt="*Educational"> 
      <img src="images/student1.jpg" class="box-img">Suspendisse vestibulum, mi ut aliquam sollicitudin, nunc 
      sem euismod sem, ut posuere quam erat eget magna. Fusce 
      sed in sapien.
      <a href="" class="anchor1">Read more...</a>
      <span class="timeMessage"></span></p>
    <p class="right-para">Suspendisse vestibulum, mi ut aliquam sollicitudin, nunc sem euismod sem, ut posuere quam erat eget magna. Fusce 
      sed in sapien.</p>
  </div>
  <div class="left-right"></div>
</div>

Inside Mid-mid

Mid-mid contains two paragraphs that are floated left of each other, called left-para and right-para, respectively. By default box-container and mid-mid have fixed height/width and overflow:hidden. Because box-container and mid-mid by default have smaller widths than left-para and right-para together, right-para is hidden beyond the bounds of box-container and mid-mid.

The anchor at the bottom of left-para has class anchor1, and on click initiates the jQuery function that changes the width of box-container and mid-mid. When classes box-container and mid-mid are switched with classes with greater or small widths, it appears that they are expanding/collapsing.

css

.box-row{
  margin: auto;
  width: 955px;
  height: 323px;
  overflow: hidden;
}
.box-container,.box-container2,.box-container3{
  float: left;
  background-image: url('../graphics/box1-fade-v.jpg');
  background-repeat: repeat-x;	
  overflow: hidden;
  height: 100%;
}

/*default */
.box-container { width: 282px; }
.mid-mid {  width: 266px; }

/* collapsed */
.box-container2 { width: 141px; }
.mid-mid2 { width: 125px; }

/* expanded */
.box-container3 {  width: 554px; }
.mid-mid3 { width: 538px; }

.mid-mid P.left-para,.mid-mid2 P.left-para,.mid-mid3 P.left-para{
  padding: 25px 0 0 15px;
  position: relative;
  width: 239px;
  margin: 0px 0px 15px 0;
  top: -15px;
}
.mid-mid P.right-para,.mid-mid2 P.right-para,.mid-mid3 P.right-para{
  padding: 10px 0px 0 35px;
  width: 232px;
  margin: 0px;
  float: left;
}

The jQuery "switches" classes mid-mid and box-container to either mid-mid2 and box-container2 (collapsed) or mid-mid3 and box-container3 (expanded). Fig. 1 illustrated the box-containers in the default state. Fig. 2 below illustrates them in the expanded state.

expanded div structure

jQuery

To bring this all together, we will take a look at the jQuery code section by section. We will start with a basic document.ready function that prevents the page from reloading when the anchor with class anchor1 is clicked.

$(document).ready(function() {			   
  function myClick(){
    return false;
  };
  $("a.anchor1").click(myClick);
})

To prevent the user from clicking anchor1 a second time before the animation is complete, we add some code to manipulate the text.

$(document).ready(function() {
  function myClick(){

$(this).hide(); $(this).next().text('One moment please...'); $(this).next().show();

return false; }; $("a.anchor1").click(myClick); })

In the box-container HTML you may have noticed an empty span right next to anchor1 with the class timeMessage. In the code above, the text within anchor1 is hidden, and timeMessage is filled with text 'One moment please...' and revealed.

We want anchor1 to come back after a moment so the user can collapse the box again when they are finished reading the content. This is where the jQuery Timers comes to use.

$(document).ready(function() {			   
  function myClick(){
    $(this).hide();
    $(this).next().text('One moment please...');
    $(this).next().show();

$(this).oneTime(1250, function() { $(this).show('slow'); $(this).next().hide(); })

return false; }; $("a.anchor1").click(myClick); })

The function oneTime comes with jQuery Timers. It simply executes the code inside the brackets one time after the amount of time specified. I have specified 1250, which is 1.25 seconds. The function causes anchor1 to slowly reappear and timeMessage to disappear again.

To summarize what the code does so far, it hides anchor1 to prevent the user from over clicking before the animations are complete. It adds a message "One moment please..." to span timeMessage. After 1.25 seconds anchor1 fades back in as timeMessage is hidden.

So how do the boxes grow and shrink? It is all about traversing the DOM tree! Take a look:

$(document).ready(function() {			   
  function myClick(){
    $(this).hide();
    $(this).next().text('One moment please...');
    $(this).next().show();

if ($(this).parent().parent().is('.mid-mid')) { $(this).html('Close'); } else{ $(this).html("Read more..."); }

$(this).oneTime(1250, function() { $(this).show('slow'); $(this).next().hide(); }) return false; }; $("a.anchor1").click(myClick); })

The user is clicking the same anchor to expand and collapse the boxes. We will need a way to tell if the box is expanded or collapsed to know how to handle a click. The if...else statement is used to check if the parent of the parent div is called 'mid-mid'.

$(document).ready(function() {			   
  function myClick(){
    $(this).hide();
    $(this).next().text('One moment please...');
    $(this).next().show();
    if ($(this).parent().parent().is('.mid-mid')) {

$(this).parent().parent().parent().siblings().children().children().fadeOut('slow');

$(this).html('Close'); } else {

$(this).parent().parent().parent().siblings().children().children().fadeIn('slow');

$(this).html("Read more..."); } $(this).oneTime(1250, function() { $(this).show('slow'); $(this).next().hide(); }) return false; }; $("a.anchor1").click(myClick); })

In the code above, if the parent of the parent is mid-mid, it will then traverse back through the DOM tree to fade out mid-mid. The next time the user clicks the link, it will no long have mid-mid as a parent of a parent, so it will do the else section of the statement.

This functionality is necessary for 2 purposes. First, one anchor and one function do all the work. Second, the content in mid-mid needs to be hidden or else in the collapsed state images and text would overflow unpredictably!

Below I am adding the final 8 lines of code. It may seem like a lot, but each line does virtually the same thing. Each line use jQuery UI switchClass function, which "Switches from the class defined in the first argument to the class defined as second argument, using an optional transition".

$(document).ready(function() {			   
  function myClick(){
    $(this).hide();
    $(this).next().text('One moment please...');
    $(this).next().show();
    if ($(this).parent().parent().is('.mid-mid')){
      $(this).parent().parent().parent().siblings().children().children().fadeOut('slow'); 

$(this).parent().parent().parent().switchClass('box-container','box-container3',650,'easeOutSine',function(){}); $(this).parent().parent().switchClass('mid-mid','mid-mid3',650,'easeOutSine',function(){}); $(this).parent().parent().parent().siblings('.box-container').switchClass('box-container','box-container2',650,'easeOutSine',function(){}); $(this).parent().parent().parent().siblings().children('.mid-mid').switchClass('mid-mid','mid-mid2',650,'easeOutSine',function(){});

$(this).html('Close'); } else {

$(this).parent().parent().parent().siblings('.box-container2').switchClass('box-container2','box-container',650,'easeOutSine',function(){}); $(this).parent().parent().parent().siblings().children('.mid-mid2').switchClass('mid-mid2','mid-mid',650,'easeOutSine',function(){}); $(this).parent().parent().parent().switchClass('box-container3','box-container',650,'easeOutSine',function(){}); $(this).parent().parent().switchClass('mid-mid3','mid-mid',650,'easeOutSine',function(){});

$(this).parent().parent().parent().siblings().children().children().fadeIn('slow'); $(this).html("Read more..."); } $(this).oneTime(1250, function() { $(this).show('slow'); $(this).next().hide(); }) return false; }; $("a.anchor1").click(myClick); })

If mid-mid is present, the default class of the selected mid-mid and box-container will switch to expanded class. The specified tween is 'easeOutSine' and with the speed '650'. At the same time, the sibling box-container and their mid-mid classes will switch from default to collapsed. Else mid-mid is not present, the code assumes that all the boxes need to be returned to their default classes.

Katie O'Connor

,

---

Comment

  1. This tutorial looks fantastic! Your graphics and wire frames really help visualize everything you are doing. Your syntax highlighter is a nice touch. Plus I love your quirky humor “Educational, Ecological, cost Effective”. You should help me with my cross domain java scripting tutorial I started… like weeks ago…

    Eric · Jan 6, 09:26 PM · #

Commenting is closed for this article.

---