stickysidebar.jquery.min.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. (function($){
  2. var settings = {
  3. speed: 350 //animation duration
  4. , easing: "linear" //use easing plugin for more options
  5. , padding: 10
  6. , constrain: false
  7. }
  8. , $window = $(window)
  9. , stickyboxes = []
  10. , methods = {
  11. init:function(opts){
  12. settings = $.extend(settings,opts);
  13. return this.each(function () {
  14. var $this = $(this);
  15. setPosition($this);
  16. stickyboxes[stickyboxes.length] = $this;
  17. moveIntoView();
  18. });
  19. }
  20. , remove:function(){
  21. return this.each(function () {
  22. var sticky = this;
  23. $.each(stickyboxes, function (i, $sb) {
  24. if($sb.get(0) === sticky){
  25. reset(null, $sb);
  26. stickyboxes.splice(i, 1);
  27. return false;
  28. }
  29. });
  30. });
  31. }
  32. , destroy: function () {
  33. $.each(stickyboxes, function (i, $sb) {
  34. reset(null, $sb);
  35. });
  36. stickyboxes=[];
  37. $window.unbind("scroll", moveIntoView);
  38. $window.unbind("resize", reset);
  39. return this;
  40. }
  41. };
  42. var moveIntoView = function () {
  43. $.each(stickyboxes, function (i, $sb) {
  44. var $this = $sb
  45. , data = $this.data("stickySB");
  46. if (data) {
  47. var sTop = $window.scrollTop() - data.offs.top
  48. , currOffs = $this.offset()
  49. , origTop = data.orig.offset.top - data.offs.top
  50. , animTo = origTop;
  51. //scrolled down out of view
  52. if (origTop < sTop) {
  53. //make sure to stop inside parent
  54. if ((sTop + settings.padding) > data.offs.bottom)
  55. animTo = data.offs.bottom;
  56. else animTo = sTop + settings.padding;
  57. }
  58. $this
  59. .stop()
  60. .animate(
  61. {top: animTo}
  62. , settings.speed
  63. , settings.easing
  64. );
  65. }
  66. });
  67. }
  68. var setPosition = function ($sb) {
  69. if ($sb) {
  70. var $this = $sb
  71. , $parent = $this.parent()
  72. , parentOffs = $parent.offset()
  73. , currOff = $this.offset()
  74. , data = $this.data("stickySB");
  75. if (!data) {
  76. data = {
  77. offs: {} // our parents offset
  78. , orig: { // cache for original css
  79. top: $this.css("top")
  80. , left: $this.css("left")
  81. , position: $this.css("position")
  82. , marginTop: $this.css("marginTop")
  83. , marginLeft: $this.css("marginLeft")
  84. , offset: $this.offset()
  85. }
  86. }
  87. }
  88. //go up the tree until we find an elem to position from
  89. while (parentOffs && "top" in parentOffs
  90. && $parent.css("position") == "static") {
  91. $parent = $parent.parent();
  92. parentOffs = $parent.offset();
  93. }
  94. if (parentOffs) { // found a postioned ancestor
  95. var padBtm = parseInt($parent.css("paddingBottom"));
  96. padBtm = isNaN(padBtm) ? 0 : padBtm;
  97. data.offs = parentOffs;
  98. data.offs.bottom = settings.constrain ?
  99. Math.abs(($parent.innerHeight() - padBtm) - $this.outerHeight()) :
  100. $(document).height();
  101. }
  102. else data.offs = { // went to far set to doc
  103. top: 0
  104. , left: 0
  105. , bottom: $(document).height()
  106. };
  107. $this.css({
  108. position: "absolute"
  109. , top: Math.floor(currOff.top - data.offs.top) + "px"
  110. , left: Math.floor(currOff.left - data.offs.left) + "px"
  111. , margin: 0
  112. , width: $this.width()
  113. }).data("stickySB", data);
  114. }
  115. }
  116. var reset = function (ev, $toReset) {
  117. var stickies = stickyboxes;
  118. if ($toReset) { // just resetting selected items
  119. stickies = [$toReset];
  120. }
  121. $.each(stickies, function(i, $sb) {
  122. var data = $sb.data("stickySB");
  123. if (data) {
  124. $sb.css({
  125. position: data.orig.position
  126. , marginTop: data.orig.marginTop
  127. , marginLeft: data.orig.marginLeft
  128. , left: data.orig.left
  129. , top: data.orig.top
  130. });
  131. if (!$toReset) { // just resetting
  132. setPosition($sb);
  133. moveIntoView();
  134. }
  135. }
  136. });
  137. }
  138. $window.bind("scroll", moveIntoView);
  139. $window.bind("resize", reset);
  140. $.fn.stickySidebar = function (method) {
  141. if (methods[method]) {
  142. return methods[method].apply(
  143. this
  144. , Array.prototype.slice.call(arguments, 1)
  145. );
  146. } else if (!method || typeof method == "object") {
  147. return methods.init.apply(this, arguments);
  148. }
  149. }
  150. })(jQuery);