relatively-sticky

A jQuery plugin for creating smart sticky elements
git clone https://git.ce9e.org/relatively-sticky.git

commit
7d521e3ed166e0513223ad13317e033edbcbd6dd
parent
539d30ee693680b3a8afa3db48a4e8573d67448c
Author
leaf corcoran <leafot@gmail.com>
Date
2013-11-16 07:04
recalc recalculates spacer, always save width, fix #9 #8

Diffstat

M jquery.sticky-kit.coffee 64 ++++++++++++++++++++++++++++++++++---------------------------
M jquery.sticky-kit.js 56 ++++++++++++++++++++++++++++++--------------------------
M jquery.sticky-kit.min.js 10 +++++-----

3 files changed, 71 insertions, 59 deletions


diff --git a/jquery.sticky-kit.coffee b/jquery.sticky-kit.coffee

@@ -13,11 +13,14 @@ $.fn.stick_in_parent = (opts={}) ->
   13    13   sticky_class ?= "is_stuck"
   14    14 
   15    15   for elm in @
   16    -1     ((elm, padding_bottom, parent_top, parent_height, top, height) ->
   -1    16     ((elm, padding_bottom, parent_top, parent_height, top, height, float) ->
   17    17       parent = elm.parent()
   18    18       parent = parent.closest(parent_selector) if parent_selector?
   19    19       throw "failed to find stick parent" unless parent.length
   20    20 
   -1    21       fixed = false
   -1    22       spacer = $("<div />")
   -1    23 
   21    24       recalc = ->
   22    25         border_top = parseInt parent.css("border-top-width"), 10
   23    26         padding_top = parseInt parent.css("padding-top"), 10
@@ -26,33 +29,39 @@ $.fn.stick_in_parent = (opts={}) ->
   26    29         parent_top = parent.offset().top + border_top + padding_top
   27    30         parent_height = parent.height()
   28    31 
   29    -1         sizing_elm = if elm.is ".is_stuck"
   30    -1           spacer
   31    -1         else
   32    -1           elm
   33    -1 
   34    -1         top = sizing_elm.offset().top - parseInt(sizing_elm.css("margin-top"), 10) - offset_top
   35    -1         height = sizing_elm.outerHeight true
   -1    32         restore = if fixed
   -1    33           fixed = false
   -1    34           elm.insertAfter(spacer).css {
   -1    35             position: ""
   -1    36             top: ""
   -1    37             width: ""
   -1    38           }
   -1    39           spacer.detach()
   -1    40           true
   -1    41 
   -1    42         top = elm.offset().top - parseInt(elm.css("margin-top"), 10) - offset_top
   -1    43         console.log "setting top", top
   -1    44 
   -1    45         height = elm.outerHeight true
   -1    46 
   -1    47         float = elm.css "float"
   -1    48         spacer.css({
   -1    49           width: elm.outerWidth true
   -1    50           height: height
   -1    51           display: elm.css "display"
   -1    52           "vertical-align": elm.css "vertical-align"
   -1    53           float: float
   -1    54         })
   -1    55 
   -1    56         if restore
   -1    57           tick()
   36    58 
   37    59       recalc()
   38    60       return if height == parent_height
   39    61 
   40    -1       # create a spacer
   41    -1       float = elm.css "float"
   42    -1 
   43    -1       spacer = $("<div />").css({
   44    -1         width: elm.outerWidth true
   45    -1         height: height
   46    -1         display: elm.css "display"
   47    -1         "vertical-align": elm.css "vertical-align"
   48    -1         float: float
   49    -1       })
   50    -1 
   51    -1       fixed = false
   52    62       bottomed = false
   53    63       last_pos = undefined
   54    64       offset = offset_top
   55    -1       reset_width = false
   56    65 
   57    66       tick = ->
   58    67         scroll = win.scrollTop()
@@ -83,9 +92,9 @@ $.fn.stick_in_parent = (opts={}) ->
   83    92             spacer.detach()
   84    93             css = {
   85    94               position: ""
   -1    95               width: ""
   86    96               top: ""
   87    97             }
   88    -1             css.width = "" if reset_width
   89    98             elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick")
   90    99 
   91   100           # updated offset
@@ -111,9 +120,7 @@ $.fn.stick_in_parent = (opts={}) ->
  111   120               top: offset
  112   121             }
  113   122 
  114    -1             if float == "none" && elm.css("display") == "block"
  115    -1               css.width = elm.width() + "px"
  116    -1               reset_width = true
   -1   123             css.width = elm.width() + "px"
  117   124 
  118   125             elm.css(css).addClass(sticky_class).after(spacer)
  119   126 
@@ -159,12 +166,13 @@ $.fn.stick_in_parent = (opts={}) ->
  159   166 
  160   167         parent.position "position", ""
  161   168 
  162    -1         if elm.is ".is_stuck"
  163    -1           elm.insertAfter(spacer).removeClass "is_stuck"
   -1   169         if fixed
   -1   170           elm.insertAfter(spacer).removeClass sticky_class
  164   171           spacer.remove()
  165   172 
  166   173       win.on "scroll", tick
  167    -1       $(document.body).on "sticky_kit:recalc", recalc
   -1   174       win.on "resize", recalc_and_tick
   -1   175       $(document.body).on "sticky_kit:recalc", recalc_and_tick
  168   176       elm.on "sticky_kit:detach", detach
  169   177 
  170   178       setTimeout tick, 0

diff --git a/jquery.sticky-kit.js b/jquery.sticky-kit.js

@@ -29,8 +29,8 @@
   29    29     if (sticky_class == null) {
   30    30       sticky_class = "is_stuck";
   31    31     }
   32    -1     _fn = function(elm, padding_bottom, parent_top, parent_height, top, height) {
   33    -1       var bottomed, detach, fixed, float, last_pos, offset, parent, recalc, recalc_and_tick, reset_width, spacer, tick;
   -1    32     _fn = function(elm, padding_bottom, parent_top, parent_height, top, height, float) {
   -1    33       var bottomed, detach, fixed, last_pos, offset, parent, recalc, recalc_and_tick, spacer, tick;
   34    34       parent = elm.parent();
   35    35       if (parent_selector != null) {
   36    36         parent = parent.closest(parent_selector);
@@ -38,34 +38,42 @@
   38    38       if (!parent.length) {
   39    39         throw "failed to find stick parent";
   40    40       }
   -1    41       fixed = false;
   -1    42       spacer = $("<div />");
   41    43       recalc = function() {
   42    -1         var border_top, padding_top, sizing_elm;
   -1    44         var border_top, padding_top, restore;
   43    45         border_top = parseInt(parent.css("border-top-width"), 10);
   44    46         padding_top = parseInt(parent.css("padding-top"), 10);
   45    47         padding_bottom = parseInt(parent.css("padding-bottom"), 10);
   46    48         parent_top = parent.offset().top + border_top + padding_top;
   47    49         parent_height = parent.height();
   48    -1         sizing_elm = elm.is(".is_stuck") ? spacer : elm;
   49    -1         top = sizing_elm.offset().top - parseInt(sizing_elm.css("margin-top"), 10) - offset_top;
   50    -1         return height = sizing_elm.outerHeight(true);
   -1    50         restore = fixed ? (fixed = false, elm.insertAfter(spacer).css({
   -1    51           position: "",
   -1    52           top: "",
   -1    53           width: ""
   -1    54         }), spacer.detach(), true) : void 0;
   -1    55         top = elm.offset().top - parseInt(elm.css("margin-top"), 10) - offset_top;
   -1    56         console.log("setting top", top);
   -1    57         height = elm.outerHeight(true);
   -1    58         float = elm.css("float");
   -1    59         spacer.css({
   -1    60           width: elm.outerWidth(true),
   -1    61           height: height,
   -1    62           display: elm.css("display"),
   -1    63           "vertical-align": elm.css("vertical-align"),
   -1    64           float: float
   -1    65         });
   -1    66         if (restore) {
   -1    67           return tick();
   -1    68         }
   51    69       };
   52    70       recalc();
   53    71       if (height === parent_height) {
   54    72         return;
   55    73       }
   56    -1       float = elm.css("float");
   57    -1       spacer = $("<div />").css({
   58    -1         width: elm.outerWidth(true),
   59    -1         height: height,
   60    -1         display: elm.css("display"),
   61    -1         "vertical-align": elm.css("vertical-align"),
   62    -1         float: float
   63    -1       });
   64    -1       fixed = false;
   65    74       bottomed = false;
   66    75       last_pos = void 0;
   67    76       offset = offset_top;
   68    -1       reset_width = false;
   69    77       tick = function() {
   70    78         var css, delta, scroll, will_bottom, win_height;
   71    79         scroll = win.scrollTop();
@@ -92,11 +100,9 @@
   92   100             spacer.detach();
   93   101             css = {
   94   102               position: "",
   -1   103               width: "",
   95   104               top: ""
   96   105             };
   97    -1             if (reset_width) {
   98    -1               css.width = "";
   99    -1             }
  100   106             elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
  101   107           }
  102   108           if (inner_scrolling) {
@@ -121,10 +127,7 @@
  121   127               position: "fixed",
  122   128               top: offset
  123   129             };
  124    -1             if (float === "none" && elm.css("display") === "block") {
  125    -1               css.width = elm.width() + "px";
  126    -1               reset_width = true;
  127    -1             }
   -1   130             css.width = elm.width() + "px";
  128   131             elm.css(css).addClass(sticky_class).after(spacer);
  129   132             if (float === "left" || float === "right") {
  130   133               spacer.append(elm);
@@ -165,13 +168,14 @@
  165   168           top: ""
  166   169         });
  167   170         parent.position("position", "");
  168    -1         if (elm.is(".is_stuck")) {
  169    -1           elm.insertAfter(spacer).removeClass("is_stuck");
   -1   171         if (fixed) {
   -1   172           elm.insertAfter(spacer).removeClass(sticky_class);
  170   173           return spacer.remove();
  171   174         }
  172   175       };
  173   176       win.on("scroll", tick);
  174    -1       $(document.body).on("sticky_kit:recalc", recalc);
   -1   177       win.on("resize", recalc_and_tick);
   -1   178       $(document.body).on("sticky_kit:recalc", recalc_and_tick);
  175   179       elm.on("sticky_kit:detach", detach);
  176   180       return setTimeout(tick, 0);
  177   181     };

diff --git a/jquery.sticky-kit.min.js b/jquery.sticky-kit.min.js

@@ -1,8 +1,8 @@
    1     1 /*
    2     2  Sticky-kit v1.0.1 | WTFPL | Leaf Corcoran 2013 | http://leafo.net
    3     3 */
    4    -1 (function(){var g,s;g=this.jQuery;s=g(window);g.fn.stick_in_parent=function(e){var w,l,f,t,u,h,D;null==e&&(e={});t=e.sticky_class;w=e.inner_scrolling;f=e.parent;l=e.offset_top;null==l&&(l=0);null==f&&(f=void 0);null==w&&(w=!0);null==t&&(t="is_stuck");u=function(a,e,h,x,A,m){var q,B,r,n,y,b,d,z,u,C,k,v;d=a.parent();null!=f&&(d=d.closest(f));if(!d.length)throw"failed to find stick parent";z=function(){var c,b;c=parseInt(d.css("border-top-width"),10);b=parseInt(d.css("padding-top"),10);e=parseInt(d.css("padding-bottom"),
    5    -1 10);h=d.offset().top+c+b;x=d.height();c=a.is(".is_stuck")?k:a;A=c.offset().top-parseInt(c.css("margin-top"),10)-l;return m=c.outerHeight(!0)};z();if(m!==x)return n=a.css("float"),k=g("<div />").css({width:a.outerWidth(!0),height:m,display:a.css("display"),"vertical-align":a.css("vertical-align"),float:n}),q=r=!1,y=void 0,b=l,C=!1,v=function(){var c,g,p,f;p=s.scrollTop();null!=y&&(g=p-y);y=p;r?(f=p+m+b>x+h,q&&!f&&(q=!1,a.css({position:"fixed",bottom:"",top:b}).trigger("sticky_kit:unbottom")),p<A&&
    6    -1 (r=!1,b=l,"left"!==n&&"right"!==n||a.insertAfter(k),k.detach(),c={position:"",top:""},C&&(c.width=""),a.css(c).removeClass(t).trigger("sticky_kit:unstick")),w&&(c=s.height(),m>c&&!q&&(b-=g,b=Math.max(c-m,b),b=Math.min(l,b),r&&a.css({top:b+"px"})))):p>A&&(r=!0,c={position:"fixed",top:b},"none"===n&&"block"===a.css("display")&&(c.width=a.width()+"px",C=!0),a.css(c).addClass(t).after(k),"left"!==n&&"right"!==n||k.append(a),a.trigger("sticky_kit:stick"));if(r&&(null==f&&(f=p+m+b>x+h),!q&&f))return q=
    7    -1 !0,"static"===d.css("position")&&d.css({position:"relative"}),a.css({position:"absolute",bottom:e,top:""}).trigger("sticky_kit:bottom")},u=function(){z();return v()},B=function(){s.off("scroll",v);g(document.body).off("sticky_kit:recalc",u);a.off("sticky_kit:detach",B);a.css({position:"",bottom:"",top:""});d.position("position","");if(a.is(".is_stuck"))return a.insertAfter(k).removeClass("is_stuck"),k.remove()},s.on("scroll",v),g(document.body).on("sticky_kit:recalc",z),a.on("sticky_kit:detach",B),
    8    -1 setTimeout(v,0)};h=0;for(D=this.length;h<D;h++)e=this[h],u(g(e));return this}}).call(this);
   -1     4 (function(){var b,q;b=this.jQuery;q=b(window);b.fn.stick_in_parent=function(e){var u,m,f,r,B,l,C;null==e&&(e={});r=e.sticky_class;u=e.inner_scrolling;f=e.parent;m=e.offset_top;null==m&&(m=0);null==f&&(f=void 0);null==u&&(u=!0);null==r&&(r="is_stuck");B=function(a,e,l,v,w,n,s){var t,z,h,x,c,d,A,y,g,k;d=a.parent();null!=f&&(d=d.closest(f));if(!d.length)throw"failed to find stick parent";h=!1;g=b("<div />");A=function(){var c,b;c=parseInt(d.css("border-top-width"),10);b=parseInt(d.css("padding-top"),
   -1     5 10);e=parseInt(d.css("padding-bottom"),10);l=d.offset().top+c+b;v=d.height();c=h?(h=!1,a.insertAfter(g).css({position:"",top:"",width:""}),g.detach(),!0):void 0;w=a.offset().top-parseInt(a.css("margin-top"),10)-m;console.log("setting top",w);n=a.outerHeight(!0);s=a.css("float");g.css({width:a.outerWidth(!0),height:n,display:a.css("display"),"vertical-align":a.css("vertical-align"),float:s});if(c)return k()};A();if(n!==v)return t=!1,x=void 0,c=m,k=function(){var b,k,p,f;p=q.scrollTop();null!=x&&(k=
   -1     6 p-x);x=p;h?(f=p+n+c>v+l,t&&!f&&(t=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom")),p<w&&(h=!1,c=m,"left"!==s&&"right"!==s||a.insertAfter(g),g.detach(),b={position:"",width:"",top:""},a.css(b).removeClass(r).trigger("sticky_kit:unstick")),u&&(b=q.height(),n>b&&!t&&(c-=k,c=Math.max(b-n,c),c=Math.min(m,c),h&&a.css({top:c+"px"})))):p>w&&(h=!0,b={position:"fixed",top:c},b.width=a.width()+"px",a.css(b).addClass(r).after(g),"left"!==s&&"right"!==s||g.append(a),a.trigger("sticky_kit:stick"));
   -1     7 if(h&&(null==f&&(f=p+n+c>v+l),!t&&f))return t=!0,"static"===d.css("position")&&d.css({position:"relative"}),a.css({position:"absolute",bottom:e,top:""}).trigger("sticky_kit:bottom")},y=function(){A();return k()},z=function(){q.off("scroll",k);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",z);a.css({position:"",bottom:"",top:""});d.position("position","");if(h)return a.insertAfter(g).removeClass(r),g.remove()},q.on("scroll",k),q.on("resize",y),b(document.body).on("sticky_kit:recalc",
   -1     8 y),a.on("sticky_kit:detach",z),setTimeout(k,0)};l=0;for(C=this.length;l<C;l++)e=this[l],B(b(e));return this}}).call(this);