sticky-kit.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // Generated by CoffeeScript 1.10.0
  2. /**
  3. @license Sticky-kit v1.1.3 | MIT | Leaf Corcoran 2015 | http://leafo.net
  4. */
  5. (function() {
  6. var $, win;
  7. $ = window.jQuery;
  8. win = $(window);
  9. $.fn.stick_in_parent = function(opts) {
  10. var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
  11. if (opts == null) {
  12. opts = {};
  13. }
  14. sticky_class = opts.sticky_class, inner_scrolling = opts.inner_scrolling, recalc_every = opts.recalc_every, parent_selector = opts.parent, offset_top = opts.offset_top, manual_spacer = opts.spacer, enable_bottoming = opts.bottoming;
  15. if (offset_top == null) {
  16. offset_top = 0;
  17. }
  18. if (parent_selector == null) {
  19. parent_selector = void 0;
  20. }
  21. if (inner_scrolling == null) {
  22. inner_scrolling = true;
  23. }
  24. if (sticky_class == null) {
  25. sticky_class = "is_stuck";
  26. }
  27. doc = $(document);
  28. if (enable_bottoming == null) {
  29. enable_bottoming = true;
  30. }
  31. outer_width = function(el) {
  32. var _el, computed, w;
  33. if (window.getComputedStyle) {
  34. _el = el[0];
  35. computed = window.getComputedStyle(el[0]);
  36. w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
  37. if (computed.getPropertyValue("box-sizing") !== "border-box") {
  38. w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
  39. }
  40. return w;
  41. } else {
  42. return el.outerWidth(true);
  43. }
  44. };
  45. fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
  46. var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
  47. if (elm.data("sticky_kit")) {
  48. return;
  49. }
  50. elm.data("sticky_kit", true);
  51. last_scroll_height = doc.height();
  52. parent = elm.parent();
  53. if (parent_selector != null) {
  54. parent = parent.closest(parent_selector);
  55. }
  56. if (!parent.length) {
  57. throw "failed to find stick parent";
  58. }
  59. fixed = false;
  60. bottomed = false;
  61. spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
  62. if (spacer) {
  63. spacer.css('position', elm.css('position'));
  64. }
  65. recalc = function() {
  66. var border_top, padding_top, restore;
  67. if (detached) {
  68. return;
  69. }
  70. last_scroll_height = doc.height();
  71. border_top = parseInt(parent.css("border-top-width"), 10);
  72. padding_top = parseInt(parent.css("padding-top"), 10);
  73. padding_bottom = parseInt(parent.css("padding-bottom"), 10);
  74. parent_top = parent.offset().top + border_top + padding_top;
  75. parent_height = parent.height();
  76. if (fixed) {
  77. fixed = false;
  78. bottomed = false;
  79. if (manual_spacer == null) {
  80. elm.insertAfter(spacer);
  81. spacer.detach();
  82. }
  83. elm.css({
  84. position: "",
  85. top: "",
  86. width: "",
  87. bottom: ""
  88. }).removeClass(sticky_class);
  89. restore = true;
  90. }
  91. top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
  92. height = elm.outerHeight(true);
  93. el_float = elm.css("float");
  94. if (spacer) {
  95. spacer.css({
  96. width: outer_width(elm),
  97. height: height,
  98. display: elm.css("display"),
  99. "vertical-align": elm.css("vertical-align"),
  100. "float": el_float
  101. });
  102. }
  103. if (restore) {
  104. return tick();
  105. }
  106. };
  107. recalc();
  108. if (height === parent_height) {
  109. return;
  110. }
  111. last_pos = void 0;
  112. offset = offset_top;
  113. recalc_counter = recalc_every;
  114. tick = function() {
  115. var css, delta, recalced, scroll, will_bottom, win_height;
  116. if (detached) {
  117. return;
  118. }
  119. recalced = false;
  120. if (recalc_counter != null) {
  121. recalc_counter -= 1;
  122. if (recalc_counter <= 0) {
  123. recalc_counter = recalc_every;
  124. recalc();
  125. recalced = true;
  126. }
  127. }
  128. if (!recalced && doc.height() !== last_scroll_height) {
  129. recalc();
  130. recalced = true;
  131. }
  132. scroll = win.scrollTop();
  133. if (last_pos != null) {
  134. delta = scroll - last_pos;
  135. }
  136. last_pos = scroll;
  137. if (fixed) {
  138. if (enable_bottoming) {
  139. will_bottom = scroll + height + offset > parent_height + parent_top;
  140. if (bottomed && !will_bottom) {
  141. bottomed = false;
  142. elm.css({
  143. position: "fixed",
  144. bottom: "",
  145. top: offset
  146. }).trigger("sticky_kit:unbottom");
  147. }
  148. }
  149. if (scroll < top) {
  150. fixed = false;
  151. offset = offset_top;
  152. if (manual_spacer == null) {
  153. if (el_float === "left" || el_float === "right") {
  154. elm.insertAfter(spacer);
  155. }
  156. spacer.detach();
  157. }
  158. css = {
  159. position: "",
  160. width: "",
  161. top: ""
  162. };
  163. elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
  164. }
  165. if (inner_scrolling) {
  166. win_height = win.height();
  167. if (height + offset_top > win_height) {
  168. if (!bottomed) {
  169. offset -= delta;
  170. offset = Math.max(win_height - height, offset);
  171. offset = Math.min(offset_top, offset);
  172. if (fixed) {
  173. elm.css({
  174. top: offset + "px"
  175. });
  176. }
  177. }
  178. }
  179. }
  180. } else {
  181. if (scroll > top) {
  182. fixed = true;
  183. css = {
  184. position: "fixed",
  185. top: offset
  186. };
  187. css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
  188. elm.css(css).addClass(sticky_class);
  189. if (manual_spacer == null) {
  190. elm.after(spacer);
  191. if (el_float === "left" || el_float === "right") {
  192. spacer.append(elm);
  193. }
  194. }
  195. elm.trigger("sticky_kit:stick");
  196. }
  197. }
  198. if (fixed && enable_bottoming) {
  199. if (will_bottom == null) {
  200. will_bottom = scroll + height + offset > parent_height + parent_top;
  201. }
  202. if (!bottomed && will_bottom) {
  203. bottomed = true;
  204. if (parent.css("position") === "static") {
  205. parent.css({
  206. position: "relative"
  207. });
  208. }
  209. return elm.css({
  210. position: "absolute",
  211. bottom: padding_bottom,
  212. top: "auto"
  213. }).trigger("sticky_kit:bottom");
  214. }
  215. }
  216. };
  217. recalc_and_tick = function() {
  218. recalc();
  219. return tick();
  220. };
  221. detach = function() {
  222. detached = true;
  223. win.off("touchmove", tick);
  224. win.off("scroll", tick);
  225. win.off("resize", recalc_and_tick);
  226. $(document.body).off("sticky_kit:recalc", recalc_and_tick);
  227. elm.off("sticky_kit:detach", detach);
  228. elm.removeData("sticky_kit");
  229. elm.css({
  230. position: "",
  231. bottom: "",
  232. top: "",
  233. width: ""
  234. });
  235. parent.position("position", "");
  236. if (fixed) {
  237. if (manual_spacer == null) {
  238. if (el_float === "left" || el_float === "right") {
  239. elm.insertAfter(spacer);
  240. }
  241. spacer.remove();
  242. }
  243. return elm.removeClass(sticky_class);
  244. }
  245. };
  246. win.on("touchmove", tick);
  247. win.on("scroll", tick);
  248. win.on("resize", recalc_and_tick);
  249. $(document.body).on("sticky_kit:recalc", recalc_and_tick);
  250. elm.on("sticky_kit:detach", detach);
  251. return setTimeout(tick, 0);
  252. };
  253. for (i = 0, len = this.length; i < len; i++) {
  254. elm = this[i];
  255. fn($(elm));
  256. }
  257. return this;
  258. };
  259. }).call(this);