$.fn.paginate = function(config){
  
  return this.each(function(i, e) {
    
    var container = $(e).css({overflow:"hidden"});
    if(container.css('position') == 'static') container.css({position:"relative"});//deal with IE6 ignoring overflow
    
    var containerHeight = container.height();
    var containerWidth = container.width();
    
    var sourceContent = container.children().remove(); //get the original elements out of the container
    
    var wrap;
    var wrapWidth = 0;
    var columns = [];
    var currentColumn = 0;
    
    var currentIndicator;
    var indicators = [];
    
    var lineTester = $('<p class="paginate_lineTester">JjGg</p>').css({display:"block", position:"absolute", left:"-999px", top:"-999px"});
    container.append(lineTester);
    var lineHeight = lineTester.height();
    
    var setupColumns = function(){
      if(wrap)
        wrap.fadeOut(200, buildColumns); //fade out before rebuilding
      else
        buildColumns();
    };
    
    var buildColumns = function(){
      
      wrapWidth = 0;
      columns = [];
      currentColumn = 0;
      currentIndicator = null;
      
      if(wrap) wrap.remove();
      
      wrap = $('<div class="wrap"></div>').css({height:"100%", position:"relative", top:"0px", left:"0px"});
      container.append(wrap);
      
      var column = newColumn();
      
      var currentChildren = [];
      var childrenHeight = 0;
      
      sourceContent.each(function(i, e){//append each child element to the current column
        
        var currentChild = $(e).clone();
        column.append(currentChild);
        
        childrenHeight += currentChild.outerHeight();//add new element to total heights
        
        if(childrenHeight > containerHeight){//the current element has broken out of the container
          
          var remainder = (childrenHeight-containerHeight); //how much of the breaking element is hanging out?
          var newChildHeight = currentChild.height()-remainder; //how much should the breaking element shrink to fit?
          
          newChildHeight -= newChildHeight % lineHeight; //acount for lineheight to avoid cutting lines in half
          var croppedChildHeight = currentChild.height()-newChildHeight;
          currentChild.css({height:newChildHeight+"px", overflow:"hidden"});
          
          //prepare for next column
          column = newColumn();
          //add the same element to the new column, offset it to only show the bits that were cropped
          currentChild = currentChild.clone().css({height:"auto"});
          column.append(currentChild);
          currentChild.css({marginTop:"-"+newChildHeight+"px"});
          childrenHeight = croppedChildHeight;
          
        }
        
        //add margins to the total
        childrenHeight += parseInt(currentChild.css('marginBottom'));
        
      });
      
      //setup indicators
      buildIndicators();
      
      //show the wrap
      wrap.fadeIn(300);
    }
    
    var newColumn = function(){
      var newColumn = $('<div></div>').css({width:containerWidth, height:containerHeight, overflow:"hidden", "float":"left"});
      wrap.append(newColumn);
      wrapWidth += containerWidth
      wrap.width(wrapWidth);
      columns.push(newColumn);
      return newColumn;
    }
    
    var goToColumn = function(columnNumber){
      // Highlight the current indicator
      if(columnNumber) currentColumn = columnNumber;
      // Update the indicator
      updateIndicator();
      //wrap.animate({left:"-"+(currentColumn*containerWidth)+"px"}, 1000);
      wrap.fadeOut(200, function(){
        wrap.css({left:"-"+(currentColumn*containerWidth)+"px"});
        wrap.fadeIn(300);
      })
      
    }
    
    var nextColumn = function(){
      if (currentColumn < columns.length - 1) {
        currentColumn++;
        goToColumn();
      }
    }
    
    var previousColumn = function(){
      if (currentColumn > 0) {
        currentColumn--;
        goToColumn();
      }
    }
    
    // Event handler for clicks on the panel indicators
    var indicatorClick = function(e) {
      var indicator = $(this);
      updateIndicator(indicator);
      currentColumn = parseInt(indicator.attr("rel"));
      goToColumn();
    };
    
    var updateIndicator = function(indicator) {
      if (!indicator) indicator = indicators[currentColumn];
      if(currentIndicator) currentIndicator.removeClass("active");
      currentIndicator = indicator;
      indicator.addClass("active");
      // Activate/Deactivate hands as needed
      if (currentColumn == columns.length - 1)
        rightHand.addClass("inactive");
      else
        rightHand.removeClass("inactive");
      if (currentColumn == 0)
        leftHand.addClass("inactive");
      else
        leftHand.removeClass("inactive");
        
      if($.browser.msie && parseInt($.browser.version) < 7) DD_belatedPNG.fix('.indicator');
    };
    
    var buildIndicators = function() {
      
      indicators = [];
      controls.empty();
      
      if(columns.length < 2) return; //dont bother if theres only one column
      
      leftHand = $('<li id="left-hand" class="inactive">Previous Page</li>');
      rightHand = $('<li id="right-hand">Next Page</li>');
    
      controls.append(leftHand);
      // Append an indicator for each
      for (var i= 0; i < columns.length; i++) {
        var rand = Math.ceil(Math.random()*3);
        var indicator = $('<li class="indicator indicator-' + rand + '" rel="' + i + '">Panel ' + (i + 1) + '</li>');
        if (i == 0) {
          currentIndicator = indicator;
          indicator.addClass("active");
        }
        indicators.push(indicator);
        indicator.click(indicatorClick);
        controls.append(indicator);
      };
      controls.append(rightHand);
      
      // Attach events to the controls.
      leftHand.click(previousColumn);
      rightHand.click(nextColumn);
      
      // Now position the indicators in the centre — this has to be done last 
      // since since all the elements need to positioned and styled in the dom
      var indicatorOffset = (controls.width() / 2)  - ((indicators[0].width() * columns.length) / 2) - leftHand.width();
      indicators[0].css({marginLeft: parseInt(indicatorOffset)+"px"});
      
      updateIndicator();
      
    };
    
    //navigation
    var controls = $('<ul id="hand-navigation"></ul>');
    $("#container").append(controls);
    var leftHand = $('<li id="left-hand" class="inactive">Previous Page</li>');
    var rightHand = $('<li id="right-hand">Next Page</li>');
    
    //setup
    setupColumns();
    
    $(window).fontResize(function(){
      
      lineHeight = lineTester.height();
      
      setupColumns(); //rebuild
      
    });
    
  });
  
}
