This jQuery plugin allows you to set a number of sidebar or floating boxes that follow the user down the page as they scroll. The plugin uses absolute positioning calculated from the original css and offset to either the closest positioned parent or to the document. The plugin has been tested in IE6-9 and all the other major browsers.

The JavaScript (jQuery)

Below is the code for the plugin, to download the code with examples use the link above.

(function($){

  var settings = {
        speed: 350 //animation duration
      , easing: "linear" //use easing plugin for more options
      , padding: 10
      , constrain: false
    }
    , $window = $(window)
    , stickyboxes = []
    , methods = {

          init:function(opts){
            settings = $.extend(settings,opts);
            return this.each(function () {
              var $this = $(this);
              setPosition($this);
              stickyboxes[stickyboxes.length] = $this;
              moveIntoView();
            });
          }

        , remove:function(){
            return this.each(function () {
              var sticky = this;
              $.each(stickyboxes, function (i, $sb) {
                if($sb.get(0) === sticky){
                reset(null, $sb);
                stickyboxes.splice(i, 1);
                return false;
                }
              });
            });
          }

        , destroy: function () {
            $.each(stickyboxes, function (i, $sb) {
              reset(null, $sb);
            });
            stickyboxes=[];
            $window.unbind("scroll", moveIntoView);
            $window.unbind("resize", reset);
            return this;
          }

      };


  var moveIntoView = function () {
    $.each(stickyboxes, function (i, $sb) {
      var $this = $sb
        , data = $this.data("stickySB");
      if (data) {
        var sTop = $window.scrollTop() - data.offs.top
          , currOffs = $this.offset()
          , origTop = data.orig.offset.top - data.offs.top
          , animTo = origTop;
        //scrolled down out of view
        if (origTop < sTop) {
//make sure to stop inside parent
          if ((sTop + settings.padding) > data.offs.bottom)
            animTo = data.offs.bottom;
          else animTo = sTop + settings.padding;
        }
        $this
          .stop()
          .animate(
              {top: animTo}
            , settings.speed
            , settings.easing
        );
      }
    });
  }

  var setPosition = function ($sb) {
    if ($sb) {
      var $this = $sb
        , $parent = $this.parent()
        , parentOffs = $parent.offset()
        , currOff = $this.offset()
        , data = $this.data("stickySB");
      if (!data) {
        data = {
            offs: {} // our parents offset
          , orig: { // cache for original css
                top: $this.css("top")
              , left: $this.css("left")
              , position: $this.css("position")
              , marginTop: $this.css("marginTop")
              , marginLeft: $this.css("marginLeft")
              , offset: $this.offset()
            }
        }
      }
      //go up the tree until we find an elem to position from
      while (parentOffs && "top" in parentOffs
        && $parent.css("position") == "static") {
        $parent = $parent.parent();
        parentOffs = $parent.offset();
      }
      if (parentOffs) { // found a postioned ancestor
        var padBtm = parseInt($parent.css("paddingBottom"));
        padBtm = isNaN(padBtm) ? 0 : padBtm;
        data.offs = parentOffs;
        data.offs.bottom = settings.constrain ?
          Math.abs(($parent.innerHeight() - padBtm) - $this.outerHeight()) :
          $(document).height();
      }
      else data.offs = { // went to far set to doc
          top: 0
        , left: 0
        , bottom: $(document).height()
      };
      $this.css({
          position: "absolute"
        , top: Math.floor(currOff.top - data.offs.top) + "px"
        , left: Math.floor(currOff.left - data.offs.left) + "px"
        , margin: 0
        , width: $this.width()
      }).data("stickySB", data);
    }
  }

  var reset = function (ev, $toReset) {
    var stickies = stickyboxes;
    if ($toReset) { // just resetting selected items
      stickies = [$toReset];
    }
    $.each(stickies, function(i, $sb) {
      var data = $sb.data("stickySB");
      if (data) {
        $sb.css({
            position: data.orig.position
          , marginTop: data.orig.marginTop
          , marginLeft: data.orig.marginLeft
          , left: data.orig.left
          , top: data.orig.top
        });
        if (!$toReset) { // just resetting
          setPosition($sb);
          moveIntoView();
        }
      }
    });
  }

  $window.bind("scroll", moveIntoView);
  $window.bind("resize", reset);

  $.fn.stickySidebar = function (method) {

    if (methods[method]) {
      return methods[method].apply(
          this
        , Array.prototype.slice.call(arguments, 1)
      );
    } else if (!method || typeof method == "object") {
      return methods.init.apply(this, arguments);
    }

  }

})(jQuery);

Usage

The plugin can be used for single or multiple boxes as shown in the examples below

A Single sticky sidebar

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="main">
  <h2>Product catalogue</h2>
  <ul id="products">
      [...]
  </ul>
</div>
<div id="side">
   <div id="basket">
     <h3>Your basket</h3>
     <p>Total: <strong>&pound;455.00</strong></p>
     <span id="items">4</span>
   </div>
</div>

For the above snippet of a HTML page we can use the following to enable the product basket as a sticky sidebar with the default options.

1
$('#basket').stickySidebar();

Multiple sticky boxes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="left">
  <h2>Left column</h2>
  <ol id="navbox" class="stickybox">
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
  </ol>
</div>
<div id="middle"></div>
  <div id="right">
    <h2>Right column</h2>
    <div id="basket" class="stickybox">
      <h3>Your basket</h3>
      <p>Total: <strong>&pound;455.00</strong></p>
      <span id="items">4</span>
    </div>
</div>

For the above example we can use the below to set the navbox and basket boxes to both be sticky sidebars with the same options.

1
$('.stickbox').stickySidebar({speed: 400, padding: 30, constrain: true})

Options

The Sticky Sidebar plugin has four options:

  1. speed – how long the animation of the box should take in milliseconds (default = 250)
  2. easing – what type of easing to use for the animation (default = “linear”)
  3. padding – how many pixels to pad the element from the top of the window (default = 10)
  4. constrain – if true stops sticky scrolling out of parent

Methods

The Sticky Sidebar plugin has two methods:

  1. remove – removes the sticky selected sticky sidebars and resets to original position
  2. destroy – removes and resets all sticky sidebars and removes event listeners


http://www.profilepicture.co.uk/tutorials/sticky-sidebar-jquery-plugin/

by Anna 안나 2012. 1. 16. 14:44