Instantly share code, notes, and snippets.
Created
May 7, 2011 21:12
-
Save p-m-p/960842 to your computer and use it in GitHub Desktop.
StickySidebar jQuery plugin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment