diff --git a/.gitignore b/.gitignore
index 6956fe0..38914f8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,4 @@ _site
sea-modules
node_modules/
.cache
+dist
diff --git a/.travis.yml b/.travis.yml
index e5c2daf..bf8de4c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,19 +1,16 @@
language: node_js
node_js:
- - 0.10
+ - "0.10"
install:
- - npm install mocha-browser nico
+ - npm install spm@ninja coveralls
before_script:
- - git clone git://github.com/aralejs/nico-arale.git _theme
- - node_modules/.bin/nico build --theme _theme -C _theme/nico.js
+ - node_modules/spm/bin/spm-install
script:
- - node_modules/.bin/mocha-browser _site/tests/runner.html -S
+ - node_modules/spm/bin/spm-test
after_success:
- - npm install jscoverage coveralls
- - node_modules/.bin/jscoverage --encoding=utf8 src _site/src-cov
- - node_modules/.bin/mocha-browser _site/tests/runner.html?cov -S -R lcov | node_modules/.bin/coveralls
+ - node_modules/spm/bin/spm-test --coveralls | node_modules/.bin/coveralls
diff --git a/HISTORY.md b/HISTORY.md
index 1fce002..fe43413 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -2,6 +2,10 @@
---
+## 1.4.0
+
+`improved` 升级到 spm@3.x 规范。
+
## 1.3.1
`tag:fixed` [#19](https://github.com/aralejs/sticky/issues/19), 绑定 window 的 resize 事件
diff --git a/dist/sticky-debug.js b/dist/sticky-debug.js
deleted file mode 100644
index 1c2d5f6..0000000
--- a/dist/sticky-debug.js
+++ /dev/null
@@ -1,281 +0,0 @@
-define("arale/sticky/1.3.1/sticky-debug", [ "$-debug" ], function(require, exports, module, undefined) {
- var $ = require("$-debug"), doc = $(document), stickyPrefix = [ "-webkit-", "-ms-", "-o-", "-moz-", "" ], guid = 0, ua = (window.navigator.userAgent || "").toLowerCase(), isIE = ua.indexOf("msie") !== -1, isIE6 = ua.indexOf("msie 6") !== -1;
- var isPositionStickySupported = checkPositionStickySupported(), isPositionFixedSupported = checkPositionFixedSupported();
- // Sticky
- // position: sticky simulator
- function Sticky(options) {
- this.options = options || {};
- this.elem = $(this.options.element);
- this.callback = options.callback || function() {};
- this.position = options.position;
- this._stickyId = guid++;
- }
- Sticky.prototype._prepare = function() {
- // save element's origin position
- var offset = this.elem.offset();
- this._originTop = offset.top;
- this._originLeft = offset.left;
- // if is fixed, force to call this_supportFixed
- if (this.position.top === Number.MAX_VALUE) {
- this._callFix = true;
- this.position.top = this._originTop;
- }
- // save element's origin style
- this._originStyles = {
- position: null,
- top: null,
- bottom: null,
- left: null
- };
- for (var style in this._originStyles) {
- if (this._originStyles.hasOwnProperty(style)) {
- this._originStyles[style] = this.elem.css(style);
- }
- }
- };
- Sticky.prototype.render = function() {
- var self = this;
- // only bind once
- if (!this.elem.length || this.elem.data("bind-sticked")) {
- return this;
- }
- this._prepare();
- // if other element change height in one page,
- // or if resize window,
- // need adjust sticky element's status
- this.adjust = function() {
- self._restore();
- var offset = self.elem.offset();
- self._originTop = offset.top;
- self._originLeft = offset.left;
- scrollFn.call(self);
- };
- var scrollFn;
- if (sticky.isPositionStickySupported && !this._callFix) {
- scrollFn = this._supportSticky;
- // set position: sticky directly
- var tmp = "";
- for (var i = 0; i < stickyPrefix.length; i++) {
- tmp += "position:" + stickyPrefix[i] + "sticky;";
- }
- if (this.position.top !== undefined) {
- tmp += "top: " + this.position.top + "px;";
- }
- if (this.position.bottom !== undefined) {
- tmp += "bottom: " + this.position.bottom + "px;";
- }
- this.elem[0].style.cssText += tmp;
- this.adjust = function() {
- scrollFn.call(self);
- };
- } else if (sticky.isPositionFixedSupported) {
- scrollFn = this._supportFixed;
- } else {
- scrollFn = this._supportAbsolute;
- // ie6
- // avoid floatImage Shake for IE6
- // see: https://github.com/lifesinger/lifesinger.
- // github.com/blob/master/lab/2009/ie6sticked_position_v4.html
- $("").appendTo("head");
- }
- // first run after document ready
- scrollFn.call(this);
- // stickyX is event namespace
- $(window).on("scroll.sticky" + this._stickyId, function() {
- if (!self.elem.is(":visible")) return;
- scrollFn.call(self);
- });
- $(window).on("resize.sticky" + this._stickyId, debounce(function() {
- self.adjust();
- }, 120));
- this.elem.data("bind-sticked", true);
- return this;
- };
- Sticky.prototype._getTopBottom = function(scrollTop, offsetTop) {
- var top;
- var bottom;
- // top is true when the distance from element to top of window <= position.top
- if (this.position.top !== undefined) {
- top = offsetTop - scrollTop <= this.position.top;
- }
- // bottom is true when the distance is from bottom of element to bottom of window <= position.bottom
- if (this.position.bottom !== undefined) {
- bottom = scrollTop + $(window).height() - offsetTop - this.elem.outerHeight() <= this.position.bottom;
- }
- return {
- top: top,
- bottom: bottom
- };
- };
- Sticky.prototype._supportFixed = function() {
- var _sticky = this.elem.data("sticked");
- var distance = this._getTopBottom(doc.scrollTop(), this._originTop);
- if (!_sticky && (distance.top !== undefined && distance.top || distance.bottom !== undefined && distance.bottom)) {
- this._addPlaceholder();
- this.elem.css($.extend({
- position: "fixed",
- left: this._originLeft
- }, distance.top ? {
- top: this.position.top
- } : {
- bottom: this.position.bottom
- }));
- this.elem.data("sticked", true);
- this.callback.call(this, true);
- } else if (_sticky && !distance.top && !distance.bottom) {
- this._restore();
- }
- };
- Sticky.prototype._supportAbsolute = function() {
- var scrollTop = doc.scrollTop();
- var _sticky = this.elem.data("sticked");
- var distance = this._getTopBottom(scrollTop, this.elem.offset().top);
- if (distance.top || distance.bottom || this._callFix) {
- // sticky status change only one time
- if (!_sticky) {
- this._addPlaceholder();
- this.elem.data("sticked", true);
- this.callback.call(this, true);
- }
- // update element's position
- this.elem.css({
- position: "absolute",
- top: this._callFix ? this._originTop + scrollTop : distance.top ? this.position.top + scrollTop : scrollTop + $(window).height() - this.position.bottom - this.elem.outerHeight()
- });
- } else if (_sticky && !distance.top && !distance.bottom) {
- this._restore();
- }
- };
- Sticky.prototype._supportSticky = function() {
- // sticky status change for callback
- var _sticky = this.elem.data("sticked");
- var distance = this._getTopBottom(doc.scrollTop(), this.elem.offset().top);
- if (!_sticky && (distance.top !== undefined && distance.top || distance.bottom !== undefined && distance.bottom)) {
- this.elem.data("sticked", true);
- this.callback.call(this, true);
- } else if (_sticky && !distance.top && !distance.bottom) {
- // don't need restore style and remove placeholder
- this.elem.data("sticked", false);
- this.callback.call(this, false);
- }
- };
- Sticky.prototype._restore = function() {
- this._removePlaceholder();
- // set origin style
- this.elem.css(this._originStyles);
- this.elem.data("sticked", false);
- this.callback.call(this, false);
- };
- // need placeholder when: 1) position: static or relative, but expect for display != block
- Sticky.prototype._addPlaceholder = function() {
- var need = false;
- var position = this.elem.css("position");
- if (position === "static" || position === "relative") {
- need = true;
- }
- if (this.elem.css("display") !== "block") {
- need = false;
- }
- if (need) {
- this._placeholder = $('
');
- this._placeholder.width(this.elem.outerWidth(true)).height(this.elem.outerHeight(true)).css("float", this.elem.css("float")).insertAfter(this.elem);
- }
- };
- Sticky.prototype._removePlaceholder = function() {
- // remove placeholder if has
- this._placeholder && this._placeholder.remove();
- };
- Sticky.prototype.destroy = function() {
- this._restore();
- this.elem.data("bind-sticked", false);
- $(window).off("scroll.sticky" + this._stickyId);
- $(window).off("resize.sticky" + this._stickyId);
- };
- // APIs
- // ---
- module.exports = sticky;
- function sticky(elem, position, callback) {
- if (!$.isPlainObject(position)) {
- position = {
- top: position
- };
- }
- if (position.top === undefined && position.bottom === undefined) {
- position.top = 0;
- }
- return new Sticky({
- element: elem,
- position: position,
- callback: callback
- }).render();
- }
- // sticky.stick(elem, position, callback)
- sticky.stick = sticky;
- // sticky.fix(elem)
- sticky.fix = function(elem) {
- return new Sticky({
- element: elem,
- // position.top is Number.MAX_VALUE means fixed
- position: {
- top: Number.MAX_VALUE
- }
- }).render();
- };
- // for tc
- sticky.isPositionStickySupported = isPositionStickySupported;
- sticky.isPositionFixedSupported = isPositionFixedSupported;
- // Helper
- // ---
- function checkPositionFixedSupported() {
- return !isIE6;
- }
- function checkPositionStickySupported() {
- if (isIE) return false;
- var container = doc[0].body;
- if (doc[0].createElement && container && container.appendChild && container.removeChild) {
- var isSupported, el = doc[0].createElement("div"), getStyle = function(st) {
- if (window.getComputedStyle) {
- return window.getComputedStyle(el).getPropertyValue(st);
- } else {
- return el.currentStyle.getAttribute(st);
- }
- };
- container.appendChild(el);
- for (var i = 0; i < stickyPrefix.length; i++) {
- el.style.cssText = "position:" + stickyPrefix[i] + "sticky;visibility:hidden;";
- if (isSupported = getStyle("position").indexOf("sticky") !== -1) break;
- }
- el.parentNode.removeChild(el);
- return isSupported;
- }
- }
- // https://github.com/jashkenas/underscore/blob/master/underscore.js#L699
- function getTime() {
- return (Date.now || function() {
- return new Date().getTime();
- })();
- }
- function debounce(func, wait, immediate) {
- var timeout, args, context, timestamp, result;
- return function() {
- context = this;
- args = arguments;
- timestamp = getTime();
- var later = function() {
- var last = getTime() - timestamp;
- if (last < wait) {
- timeout = setTimeout(later, wait - last);
- } else {
- timeout = null;
- if (!immediate) result = func.apply(context, args);
- }
- };
- var callNow = immediate && !timeout;
- if (!timeout) {
- timeout = setTimeout(later, wait);
- }
- if (callNow) result = func.apply(context, args);
- return result;
- };
- }
-});
diff --git a/dist/sticky.js b/dist/sticky.js
deleted file mode 100644
index 19a33a4..0000000
--- a/dist/sticky.js
+++ /dev/null
@@ -1 +0,0 @@
-define("arale/sticky/1.3.1/sticky",["$"],function(a,b,c,d){function e(a){this.options=a||{},this.elem=k(this.options.element),this.callback=a.callback||function(){},this.position=a.position,this._stickyId=n++}function f(a,b,c){return k.isPlainObject(b)||(b={top:b}),b.top===d&&b.bottom===d&&(b.top=0),new e({element:a,position:b,callback:c}).render()}function g(){return!q}function h(){if(p)return!1;var a=l[0].body;if(l[0].createElement&&a&&a.appendChild&&a.removeChild){var b,c=l[0].createElement("div"),d=function(a){return window.getComputedStyle?window.getComputedStyle(c).getPropertyValue(a):c.currentStyle.getAttribute(a)};a.appendChild(c);for(var e=0;ek?d=setTimeout(j,b-k):(d=null,c||(h=a.apply(f,e)))},k=c&&!d;return d||(d=setTimeout(j,b)),k&&(h=a.apply(f,e)),h}}var k=a("$"),l=k(document),m=["-webkit-","-ms-","-o-","-moz-",""],n=0,o=(window.navigator.userAgent||"").toLowerCase(),p=-1!==o.indexOf("msie"),q=-1!==o.indexOf("msie 6"),r=h(),s=g();e.prototype._prepare=function(){var a=this.elem.offset();this._originTop=a.top,this._originLeft=a.left,this.position.top===Number.MAX_VALUE&&(this._callFix=!0,this.position.top=this._originTop),this._originStyles={position:null,top:null,bottom:null,left:null};for(var b in this._originStyles)this._originStyles.hasOwnProperty(b)&&(this._originStyles[b]=this.elem.css(b))},e.prototype.render=function(){var a=this;if(!this.elem.length||this.elem.data("bind-sticked"))return this;this._prepare(),this.adjust=function(){a._restore();var c=a.elem.offset();a._originTop=c.top,a._originLeft=c.left,b.call(a)};var b;if(f.isPositionStickySupported&&!this._callFix){b=this._supportSticky;for(var c="",e=0;e * html{ background:url(null) no-repeat fixed; } ").appendTo("head"));return b.call(this),k(window).on("scroll.sticky"+this._stickyId,function(){a.elem.is(":visible")&&b.call(a)}),k(window).on("resize.sticky"+this._stickyId,j(function(){a.adjust()},120)),this.elem.data("bind-sticked",!0),this},e.prototype._getTopBottom=function(a,b){var c,e;return this.position.top!==d&&(c=b-a<=this.position.top),this.position.bottom!==d&&(e=a+k(window).height()-b-this.elem.outerHeight()<=this.position.bottom),{top:c,bottom:e}},e.prototype._supportFixed=function(){var a=this.elem.data("sticked"),b=this._getTopBottom(l.scrollTop(),this._originTop);!a&&(b.top!==d&&b.top||b.bottom!==d&&b.bottom)?(this._addPlaceholder(),this.elem.css(k.extend({position:"fixed",left:this._originLeft},b.top?{top:this.position.top}:{bottom:this.position.bottom})),this.elem.data("sticked",!0),this.callback.call(this,!0)):!a||b.top||b.bottom||this._restore()},e.prototype._supportAbsolute=function(){var a=l.scrollTop(),b=this.elem.data("sticked"),c=this._getTopBottom(a,this.elem.offset().top);c.top||c.bottom||this._callFix?(b||(this._addPlaceholder(),this.elem.data("sticked",!0),this.callback.call(this,!0)),this.elem.css({position:"absolute",top:this._callFix?this._originTop+a:c.top?this.position.top+a:a+k(window).height()-this.position.bottom-this.elem.outerHeight()})):!b||c.top||c.bottom||this._restore()},e.prototype._supportSticky=function(){var a=this.elem.data("sticked"),b=this._getTopBottom(l.scrollTop(),this.elem.offset().top);!a&&(b.top!==d&&b.top||b.bottom!==d&&b.bottom)?(this.elem.data("sticked",!0),this.callback.call(this,!0)):!a||b.top||b.bottom||(this.elem.data("sticked",!1),this.callback.call(this,!1))},e.prototype._restore=function(){this._removePlaceholder(),this.elem.css(this._originStyles),this.elem.data("sticked",!1),this.callback.call(this,!1)},e.prototype._addPlaceholder=function(){var a=!1,b=this.elem.css("position");("static"===b||"relative"===b)&&(a=!0),"block"!==this.elem.css("display")&&(a=!1),a&&(this._placeholder=k(''),this._placeholder.width(this.elem.outerWidth(!0)).height(this.elem.outerHeight(!0)).css("float",this.elem.css("float")).insertAfter(this.elem))},e.prototype._removePlaceholder=function(){this._placeholder&&this._placeholder.remove()},e.prototype.destroy=function(){this._restore(),this.elem.data("bind-sticked",!1),k(window).off("scroll.sticky"+this._stickyId),k(window).off("resize.sticky"+this._stickyId)},c.exports=f,f.stick=f,f.fix=function(a){return new e({element:a,position:{top:Number.MAX_VALUE}}).render()},f.isPositionStickySupported=r,f.isPositionFixedSupported=s});
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..de05797
--- /dev/null
+++ b/index.js
@@ -0,0 +1,345 @@
+var $ = require("jquery"),
+ doc = $(document),
+ stickyPrefix = ["-webkit-", "-ms-", "-o-", "-moz-", ""],
+ guid = 0,
+
+ ua = (window.navigator.userAgent || "").toLowerCase(),
+ isIE = ua.indexOf("msie") !== -1,
+ isIE6 = ua.indexOf("msie 6") !== -1;
+
+var isPositionStickySupported = checkPositionStickySupported(),
+ isPositionFixedSupported = checkPositionFixedSupported();
+
+
+// Sticky
+// position: sticky simulator
+function Sticky(options) {
+ this.options = options || {};
+ this.elem = $(this.options.element);
+ this.callback = options.callback || function() {};
+ this.position = options.position;
+ this._stickyId = guid++;
+}
+
+Sticky.prototype._prepare = function() {
+ // save element's origin position
+ var offset = this.elem.offset();
+ this._originTop = offset.top;
+ this._originLeft = offset.left;
+
+ // if is fixed, force to call this_supportFixed
+ if (this.position.top === Number.MAX_VALUE) {
+ this._callFix = true;
+ this.position.top = this._originTop;
+ }
+
+ // save element's origin style
+ this._originStyles = {
+ position: null,
+ top: null,
+ bottom: null,
+ left: null
+ };
+ for (var style in this._originStyles) {
+ if (this._originStyles.hasOwnProperty(style)) {
+ this._originStyles[style] = this.elem.css(style);
+ }
+ }
+};
+
+Sticky.prototype.render = function () {
+ var self = this;
+
+ // only bind once
+ if (!this.elem.length || this.elem.data('bind-sticked')) {
+ return this;
+ }
+
+ this._prepare();
+
+ // if other element change height in one page,
+ // or if resize window,
+ // need adjust sticky element's status
+ this.adjust = function() {
+ self._restore();
+
+ var offset = self.elem.offset();
+ self._originTop = offset.top;
+ self._originLeft = offset.left;
+
+ scrollFn.call(self);
+ };
+
+ var scrollFn;
+ if (sticky.isPositionStickySupported && !this._callFix) {
+ scrollFn = this._supportSticky;
+
+ // set position: sticky directly
+ var tmp = "";
+ for (var i = 0; i < stickyPrefix.length; i++) {
+ tmp += "position:" + stickyPrefix[i] + "sticky;";
+ }
+ if (this.position.top !== undefined) {
+ tmp += "top: " + this.position.top + "px;";
+ }
+ if (this.position.bottom !== undefined) {
+ tmp += "bottom: " + this.position.bottom + "px;";
+ }
+ this.elem[0].style.cssText += tmp;
+
+ this.adjust = function() {
+ scrollFn.call(self);
+ };
+ } else if (sticky.isPositionFixedSupported) {
+ scrollFn = this._supportFixed;
+ } else {
+ scrollFn = this._supportAbsolute; // ie6
+ // avoid floatImage Shake for IE6
+ // see: https://github.com/lifesinger/lifesinger.
+ // github.com/blob/master/lab/2009/ie6sticked_position_v4.html
+ $("").appendTo("head");
+ }
+
+ // first run after document ready
+ scrollFn.call(this);
+
+ // stickyX is event namespace
+ $(window).on('scroll.sticky' + this._stickyId, function () {
+ if (!self.elem.is(':visible')) return;
+ scrollFn.call(self);
+ });
+
+ $(window).on('resize.sticky' + this._stickyId, debounce(function() {
+ self.adjust();
+ }, 120));
+
+ this.elem.data('bind-sticked', true);
+
+ return this;
+};
+
+Sticky.prototype._getTopBottom = function(scrollTop, offsetTop) {
+ var top;
+ var bottom;
+
+ // top is true when the distance from element to top of window <= position.top
+ if (this.position.top !== undefined) {
+ top = offsetTop - scrollTop <= this.position.top;
+ }
+ // bottom is true when the distance is from bottom of element to bottom of window <= position.bottom
+ if (this.position.bottom !== undefined) {
+ bottom = scrollTop + $(window).height() - offsetTop - this.elem.outerHeight() <= this.position.bottom;
+ }
+
+ return {
+ top: top,
+ bottom: bottom
+ };
+};
+
+Sticky.prototype._supportFixed = function () {
+ var _sticky = this.elem.data('sticked');
+ var distance = this._getTopBottom(doc.scrollTop(), this._originTop);
+
+ if (!_sticky &&
+ (distance.top !== undefined && distance.top ||
+ distance.bottom !== undefined && distance.bottom)) {
+ this._addPlaceholder();
+
+ this.elem.css($.extend({
+ position: 'fixed',
+ left: this._originLeft
+ }, distance.top ? { top: this.position.top } : { bottom: this.position.bottom }));
+ this.elem.data('sticked', true);
+ this.callback.call(this, true);
+ } else if (_sticky && !distance.top && !distance.bottom) {
+ this._restore();
+ }
+};
+
+Sticky.prototype._supportAbsolute = function () {
+ var scrollTop = doc.scrollTop();
+ var _sticky = this.elem.data('sticked');
+ var distance = this._getTopBottom(scrollTop, this.elem.offset().top);
+
+ if (distance.top || distance.bottom || this._callFix) {
+ // sticky status change only one time
+ if (!_sticky) {
+ this._addPlaceholder();
+ this.elem.data('sticked', true);
+ this.callback.call(this, true);
+ }
+ // update element's position
+ this.elem.css({
+ position: 'absolute',
+ top: this._callFix ? this._originTop + scrollTop: (distance.top ? this.position.top + scrollTop :
+ scrollTop + $(window).height() - this.position.bottom - this.elem.outerHeight())
+ });
+ } else if (_sticky && !distance.top && !distance.bottom) {
+ this._restore();
+ }
+};
+
+Sticky.prototype._supportSticky = function () {
+ // sticky status change for callback
+ var _sticky = this.elem.data('sticked');
+ var distance = this._getTopBottom(doc.scrollTop(), this.elem.offset().top);
+
+ if (!_sticky &&
+ (distance.top !== undefined && distance.top ||
+ distance.bottom !== undefined && distance.bottom)) {
+ this.elem.data('sticked', true);
+ this.callback.call(this, true);
+ } else if (_sticky && !distance.top && !distance.bottom){
+ // don't need restore style and remove placeholder
+ this.elem.data('sticked', false);
+ this.callback.call(this, false);
+ }
+};
+
+Sticky.prototype._restore = function () {
+ this._removePlaceholder();
+
+ // set origin style
+ this.elem.css(this._originStyles);
+
+ this.elem.data('sticked', false);
+
+ this.callback.call(this, false);
+};
+
+// need placeholder when: 1) position: static or relative, but expect for display != block
+Sticky.prototype._addPlaceholder = function() {
+ var need = false;
+ var position = this.elem.css("position");
+
+ if (position === 'static' || position === 'relative') {
+ need = true;
+ }
+ if (this.elem.css("display") !== "block") {
+ need = false;
+ }
+
+ if (need) {
+ this._placeholder = $('');
+ this._placeholder.width(this.elem.outerWidth(true))
+ .height(this.elem.outerHeight(true))
+ .css("float", this.elem.css("float")).insertAfter(this.elem);
+ }
+};
+
+Sticky.prototype._removePlaceholder = function() {
+ // remove placeholder if has
+ this._placeholder && this._placeholder.remove();
+};
+
+Sticky.prototype.destroy = function () {
+ this._restore();
+ this.elem.data("bind-sticked", false);
+ $(window).off('scroll.sticky' + this._stickyId);
+ $(window).off('resize.sticky' + this._stickyId);
+};
+
+// APIs
+// ---
+
+module.exports = sticky;
+
+function sticky(elem, position, callback) {
+ if (!$.isPlainObject(position)) {
+ position = {
+ top: position
+ };
+ }
+ if (position.top === undefined && position.bottom === undefined) {
+ position.top = 0;
+ }
+ return (new Sticky({
+ element: elem,
+ position: position,
+ callback: callback
+ })).render();
+}
+
+// sticky.stick(elem, position, callback)
+sticky.stick = sticky;
+
+// sticky.fix(elem)
+sticky.fix = function (elem) {
+ return (new Sticky({
+ element: elem,
+ // position.top is Number.MAX_VALUE means fixed
+ position: {
+ top: Number.MAX_VALUE
+ }
+ })).render();
+};
+
+// for tc
+sticky.isPositionStickySupported = isPositionStickySupported;
+sticky.isPositionFixedSupported = isPositionFixedSupported;
+
+// Helper
+// ---
+function checkPositionFixedSupported() {
+ return !isIE6;
+}
+
+function checkPositionStickySupported() {
+ if (isIE) return false;
+
+ var container = doc[0].body;
+
+ if (doc[0].createElement && container && container.appendChild && container.removeChild) {
+ var isSupported,
+ el = doc[0].createElement("div"),
+ getStyle = function (st) {
+ if (window.getComputedStyle) {
+ return window.getComputedStyle(el).getPropertyValue(st);
+ } else {
+ return el.currentStyle.getAttribute(st);
+ }
+ };
+
+ container.appendChild(el);
+
+ for (var i = 0; i < stickyPrefix.length; i++) {
+ el.style.cssText = "position:" + stickyPrefix[i] + "sticky;visibility:hidden;";
+ if (isSupported = getStyle("position").indexOf("sticky") !== -1) break;
+ }
+
+ el.parentNode.removeChild(el);
+ return isSupported;
+ }
+}
+
+// https://github.com/jashkenas/underscore/blob/master/underscore.js#L699
+function getTime() {
+ return (Date.now || function() {
+ return new Date().getTime();
+ })()
+}
+function debounce(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = getTime();
+ var later = function() {
+ var last = getTime() - timestamp;
+ if (last < wait) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) result = func.apply(context, args);
+ }
+ };
+ var callNow = immediate && !timeout;
+ if (!timeout) {
+ timeout = setTimeout(later, wait);
+ }
+ if (callNow) result = func.apply(context, args);
+ return result;
+ };
+}
diff --git a/package.json b/package.json
index e70dd79..8bc56fc 100644
--- a/package.json
+++ b/package.json
@@ -1,28 +1,36 @@
{
- "family": "arale",
- "name": "sticky",
- "version": "1.3.1",
- "keywords": ["utility"],
- "description": "实现元素跟随滚动的效果。",
- "homepage": "http://aralejs.org/sticky/",
- "author": "乔花 ",
- "maintainers": [
- "乔花 ",
- "偏右 "
- ],
- "repository": {
- "type": "git",
- "url": "https://github.com/aralejs/sticky"
+ "name": "arale-sticky",
+ "version": "1.4.0",
+ "keywords": [
+ "utility"
+ ],
+ "description": "实现元素跟随滚动的效果。",
+ "homepage": "http://aralejs.org/sticky/",
+ "author": "乔花 ",
+ "maintainers": [
+ "乔花 ",
+ "偏右 "
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/aralejs/sticky"
+ },
+ "bugs": {
+ "url": "https://github.com/aralejs/sticky/issues"
+ },
+ "license": "MIT",
+ "spm": {
+ "main": "index.js",
+ "dependencies": {
+ "jquery": "1.7.2"
},
- "bugs": {
- "url": "https://github.com/aralejs/sticky/issues"
+ "devDependencies": {
+ "expect.js": "0.3.1",
+ "sinon": "1.6.0"
},
- "license": "MIT",
- "spm": {
- "alias": {
- "$": "$"
- },
- "output": ["sticky.js"]
- },
- "tests": ["sticky"]
+ "buildArgs": "--ignore jquery"
+ },
+ "tests": [
+ "sticky"
+ ]
}
diff --git a/src/sticky.js b/src/sticky.js
deleted file mode 100644
index c844fa5..0000000
--- a/src/sticky.js
+++ /dev/null
@@ -1,348 +0,0 @@
-define(function (require, exports, module, undefined) {
-
- var $ = require("$"),
- doc = $(document),
- stickyPrefix = ["-webkit-", "-ms-", "-o-", "-moz-", ""],
- guid = 0,
-
- ua = (window.navigator.userAgent || "").toLowerCase(),
- isIE = ua.indexOf("msie") !== -1,
- isIE6 = ua.indexOf("msie 6") !== -1;
-
- var isPositionStickySupported = checkPositionStickySupported(),
- isPositionFixedSupported = checkPositionFixedSupported();
-
-
- // Sticky
- // position: sticky simulator
- function Sticky(options) {
- this.options = options || {};
- this.elem = $(this.options.element);
- this.callback = options.callback || function() {};
- this.position = options.position;
- this._stickyId = guid++;
- }
-
- Sticky.prototype._prepare = function() {
- // save element's origin position
- var offset = this.elem.offset();
- this._originTop = offset.top;
- this._originLeft = offset.left;
-
- // if is fixed, force to call this_supportFixed
- if (this.position.top === Number.MAX_VALUE) {
- this._callFix = true;
- this.position.top = this._originTop;
- }
-
- // save element's origin style
- this._originStyles = {
- position: null,
- top: null,
- bottom: null,
- left: null
- };
- for (var style in this._originStyles) {
- if (this._originStyles.hasOwnProperty(style)) {
- this._originStyles[style] = this.elem.css(style);
- }
- }
- };
-
- Sticky.prototype.render = function () {
- var self = this;
-
- // only bind once
- if (!this.elem.length || this.elem.data('bind-sticked')) {
- return this;
- }
-
- this._prepare();
-
- // if other element change height in one page,
- // or if resize window,
- // need adjust sticky element's status
- this.adjust = function() {
- self._restore();
-
- var offset = self.elem.offset();
- self._originTop = offset.top;
- self._originLeft = offset.left;
-
- scrollFn.call(self);
- };
-
- var scrollFn;
- if (sticky.isPositionStickySupported && !this._callFix) {
- scrollFn = this._supportSticky;
-
- // set position: sticky directly
- var tmp = "";
- for (var i = 0; i < stickyPrefix.length; i++) {
- tmp += "position:" + stickyPrefix[i] + "sticky;";
- }
- if (this.position.top !== undefined) {
- tmp += "top: " + this.position.top + "px;";
- }
- if (this.position.bottom !== undefined) {
- tmp += "bottom: " + this.position.bottom + "px;";
- }
- this.elem[0].style.cssText += tmp;
-
- this.adjust = function() {
- scrollFn.call(self);
- };
- } else if (sticky.isPositionFixedSupported) {
- scrollFn = this._supportFixed;
- } else {
- scrollFn = this._supportAbsolute; // ie6
- // avoid floatImage Shake for IE6
- // see: https://github.com/lifesinger/lifesinger.
- // github.com/blob/master/lab/2009/ie6sticked_position_v4.html
- $("").appendTo("head");
- }
-
- // first run after document ready
- scrollFn.call(this);
-
- // stickyX is event namespace
- $(window).on('scroll.sticky' + this._stickyId, function () {
- if (!self.elem.is(':visible')) return;
- scrollFn.call(self);
- });
-
- $(window).on('resize.sticky' + this._stickyId, debounce(function() {
- self.adjust();
- }, 120));
-
- this.elem.data('bind-sticked', true);
-
- return this;
- };
-
- Sticky.prototype._getTopBottom = function(scrollTop, offsetTop) {
- var top;
- var bottom;
-
- // top is true when the distance from element to top of window <= position.top
- if (this.position.top !== undefined) {
- top = offsetTop - scrollTop <= this.position.top;
- }
- // bottom is true when the distance is from bottom of element to bottom of window <= position.bottom
- if (this.position.bottom !== undefined) {
- bottom = scrollTop + $(window).height() - offsetTop - this.elem.outerHeight() <= this.position.bottom;
- }
-
- return {
- top: top,
- bottom: bottom
- };
- };
-
- Sticky.prototype._supportFixed = function () {
- var _sticky = this.elem.data('sticked');
- var distance = this._getTopBottom(doc.scrollTop(), this._originTop);
-
- if (!_sticky &&
- (distance.top !== undefined && distance.top ||
- distance.bottom !== undefined && distance.bottom)) {
- this._addPlaceholder();
-
- this.elem.css($.extend({
- position: 'fixed',
- left: this._originLeft
- }, distance.top ? { top: this.position.top } : { bottom: this.position.bottom }));
- this.elem.data('sticked', true);
- this.callback.call(this, true);
- } else if (_sticky && !distance.top && !distance.bottom) {
- this._restore();
- }
- };
-
- Sticky.prototype._supportAbsolute = function () {
- var scrollTop = doc.scrollTop();
- var _sticky = this.elem.data('sticked');
- var distance = this._getTopBottom(scrollTop, this.elem.offset().top);
-
- if (distance.top || distance.bottom || this._callFix) {
- // sticky status change only one time
- if (!_sticky) {
- this._addPlaceholder();
- this.elem.data('sticked', true);
- this.callback.call(this, true);
- }
- // update element's position
- this.elem.css({
- position: 'absolute',
- top: this._callFix ? this._originTop + scrollTop: (distance.top ? this.position.top + scrollTop :
- scrollTop + $(window).height() - this.position.bottom - this.elem.outerHeight())
- });
- } else if (_sticky && !distance.top && !distance.bottom) {
- this._restore();
- }
- };
-
- Sticky.prototype._supportSticky = function () {
- // sticky status change for callback
- var _sticky = this.elem.data('sticked');
- var distance = this._getTopBottom(doc.scrollTop(), this.elem.offset().top);
-
- if (!_sticky &&
- (distance.top !== undefined && distance.top ||
- distance.bottom !== undefined && distance.bottom)) {
- this.elem.data('sticked', true);
- this.callback.call(this, true);
- } else if (_sticky && !distance.top && !distance.bottom){
- // don't need restore style and remove placeholder
- this.elem.data('sticked', false);
- this.callback.call(this, false);
- }
- };
-
- Sticky.prototype._restore = function () {
- this._removePlaceholder();
-
- // set origin style
- this.elem.css(this._originStyles);
-
- this.elem.data('sticked', false);
-
- this.callback.call(this, false);
- };
-
- // need placeholder when: 1) position: static or relative, but expect for display != block
- Sticky.prototype._addPlaceholder = function() {
- var need = false;
- var position = this.elem.css("position");
-
- if (position === 'static' || position === 'relative') {
- need = true;
- }
- if (this.elem.css("display") !== "block") {
- need = false;
- }
-
- if (need) {
- this._placeholder = $('');
- this._placeholder.width(this.elem.outerWidth(true))
- .height(this.elem.outerHeight(true))
- .css("float", this.elem.css("float")).insertAfter(this.elem);
- }
- };
-
- Sticky.prototype._removePlaceholder = function() {
- // remove placeholder if has
- this._placeholder && this._placeholder.remove();
- };
-
- Sticky.prototype.destroy = function () {
- this._restore();
- this.elem.data("bind-sticked", false);
- $(window).off('scroll.sticky' + this._stickyId);
- $(window).off('resize.sticky' + this._stickyId);
- };
-
- // APIs
- // ---
-
- module.exports = sticky;
-
- function sticky(elem, position, callback) {
- if (!$.isPlainObject(position)) {
- position = {
- top: position
- };
- }
- if (position.top === undefined && position.bottom === undefined) {
- position.top = 0;
- }
- return (new Sticky({
- element: elem,
- position: position,
- callback: callback
- })).render();
- }
-
- // sticky.stick(elem, position, callback)
- sticky.stick = sticky;
-
- // sticky.fix(elem)
- sticky.fix = function (elem) {
- return (new Sticky({
- element: elem,
- // position.top is Number.MAX_VALUE means fixed
- position: {
- top: Number.MAX_VALUE
- }
- })).render();
- };
-
- // for tc
- sticky.isPositionStickySupported = isPositionStickySupported;
- sticky.isPositionFixedSupported = isPositionFixedSupported;
-
- // Helper
- // ---
- function checkPositionFixedSupported() {
- return !isIE6;
- }
-
- function checkPositionStickySupported() {
- if (isIE) return false;
-
- var container = doc[0].body;
-
- if (doc[0].createElement && container && container.appendChild && container.removeChild) {
- var isSupported,
- el = doc[0].createElement("div"),
- getStyle = function (st) {
- if (window.getComputedStyle) {
- return window.getComputedStyle(el).getPropertyValue(st);
- } else {
- return el.currentStyle.getAttribute(st);
- }
- };
-
- container.appendChild(el);
-
- for (var i = 0; i < stickyPrefix.length; i++) {
- el.style.cssText = "position:" + stickyPrefix[i] + "sticky;visibility:hidden;";
- if (isSupported = getStyle("position").indexOf("sticky") !== -1) break;
- }
-
- el.parentNode.removeChild(el);
- return isSupported;
- }
- }
-
- // https://github.com/jashkenas/underscore/blob/master/underscore.js#L699
- function getTime() {
- return (Date.now || function() {
- return new Date().getTime();
- })()
- }
- function debounce(func, wait, immediate) {
- var timeout, args, context, timestamp, result;
- return function() {
- context = this;
- args = arguments;
- timestamp = getTime();
- var later = function() {
- var last = getTime() - timestamp;
- if (last < wait) {
- timeout = setTimeout(later, wait - last);
- } else {
- timeout = null;
- if (!immediate) result = func.apply(context, args);
- }
- };
- var callNow = immediate && !timeout;
- if (!timeout) {
- timeout = setTimeout(later, wait);
- }
- if (callNow) result = func.apply(context, args);
- return result;
- };
- }
-});
diff --git a/tests/sticky-spec.js b/tests/sticky-spec.js
index 75f9c1d..ec7afb5 100644
--- a/tests/sticky-spec.js
+++ b/tests/sticky-spec.js
@@ -1,435 +1,432 @@
-define(function (require) {
+//mocha.setup({ignoreLeaks: true});
- //mocha.setup({ignoreLeaks: true});
+var expect = require('expect.js');
+var $ = require('jquery');
+var sinon = require('sinon');
- var expect = require('expect');
- var $ = require('$');
- var sinon = require('sinon');
+var element = null;
+var setTop = 50;
+var elementTop;
+var elementBottom;
+var timeout = 30;
+var tmp1, tmp2, tmpHeight = 1200;
- var element = null;
- var setTop = 50;
- var elementTop;
- var elementBottom;
- var timeout = 30;
- var tmp1, tmp2, tmpHeight = 1200;
+var Sticky = require('../index.js');
- var Sticky = require('sticky');
+var isPositionStickySupported = Sticky.isPositionStickySupported,
+ isPositionFixedSupported = Sticky.isPositionFixedSupported;
- var isPositionStickySupported = Sticky.isPositionStickySupported,
- isPositionFixedSupported = Sticky.isPositionFixedSupported;
+describe('Sticky.fix', function () {
+ beforeEach(function () {
+ $('body').css('height', '2000px');
+ element = $('test
');
+ element.appendTo('body');
+ });
- describe('Sticky.fix', function () {
- beforeEach(function () {
- $('body').css('height', '2000px');
- element = $('test
');
- element.appendTo('body');
- });
+ afterEach(function () {
+ element.remove();
+ element = null;
+ $('body').css('height', '');
+ $(document).off('scroll');
+ $(document).scrollTop(0);
+ });
+
+ it('默认的 top 值', function () {
+ var originTop = element.offset().top;
+ var obj = Sticky.fix(element);
+ expect(obj.position.top).to.be(originTop);
+ obj.destroy();
+ });
- afterEach(function () {
- element.remove();
- element = null;
- $('body').css('height', '');
- $(document).off('scroll');
- $(document).scrollTop(0);
- });
-
- it('默认的 top 值', function () {
- var originTop = element.offset().top;
- var obj = Sticky.fix(element);
- expect(obj.position.top).to.be(originTop);
- obj.destroy();
- });
+ it('fixed 元素, 滚动 500 像素', function (done) {
+ var oldTop = element.offset().top;
- it('fixed 元素, 滚动 500 像素', function (done) {
- var oldTop = element.offset().top;
+ var obj = Sticky.fix(element);
- var obj = Sticky.fix(element);
+ $(document).scrollTop(500);
- $(document).scrollTop(500);
+ setTimeout(function () {
+ expect(element.css('position')).to.be(isPositionFixedSupported ? 'fixed' : 'absolute');
+ expect(obj._placeholder.length).to.be(1);
+ expect(element.offset().top).to.be(oldTop + 500);
+ done();
- setTimeout(function () {
- expect(element.css('position')).to.be(isPositionFixedSupported ? 'fixed' : 'absolute');
- expect(obj._placeholder.length).to.be(1);
- expect(element.offset().top).to.be(oldTop + 500);
- done();
+ obj.destroy();
+ }, timeout);
+ });
- obj.destroy();
- }, timeout);
- });
+ it('不需要占位符的 fixed 元素', function (done) {
+ element.css("position", "absolute");
- it('不需要占位符的 fixed 元素', function (done) {
- element.css("position", "absolute");
+ var obj = Sticky.fix(element);
+ $(document).scrollTop(500);
- var obj = Sticky.fix(element);
- $(document).scrollTop(500);
+ setTimeout(function () {
+ expect(obj._placeholder).to.be(undefined);
+ done();
+ obj.destroy();
+ }, timeout);
+ });
+
+ it('float: left 时', function (done) {
+ element.css("float", "left");
- setTimeout(function () {
- expect(obj._placeholder).to.be(undefined);
- done();
- obj.destroy();
- }, timeout);
- });
-
- it('float: left 时', function (done) {
- element.css("float", "left");
+ var obj = Sticky.fix(element);
+ $(document).scrollTop(500);
- var obj = Sticky.fix(element);
- $(document).scrollTop(500);
+ setTimeout(function () {
+ expect(obj._placeholder.length).to.be(1);
+ done();
+ obj.destroy();
+ }, timeout);
- setTimeout(function () {
- expect(obj._placeholder.length).to.be(1);
- done();
- obj.destroy();
- }, timeout);
+ });
- });
+ it('重复绑定', function (done) {
+ var obj1 = Sticky.fix(element);
- it('重复绑定', function (done) {
- var obj1 = Sticky.fix(element);
+ var obj2 = Sticky.fix(element);
- var obj2 = Sticky.fix(element);
+ $(document).scrollTop(500);
- $(document).scrollTop(500);
+ setTimeout(function () {
+ expect(element.data("bind-sticked")).to.be(true);
+ expect(obj2.adjust).to.be(undefined);
+ done();
- setTimeout(function () {
- expect(element.data("bind-sticked")).to.be(true);
- expect(obj2.adjust).to.be(undefined);
- done();
+ obj1.destroy();
+ }, timeout);
+ });
+});
- obj1.destroy();
- }, timeout);
- });
+describe('Sticky.stick', function () {
+ beforeEach(function () {
+ tmp1 = $('').height(1200).prependTo("body");
+ element = $('test
');
+ element.appendTo('body');
+ elementTop = element.offset().top - setTop;
+ elementBottom = element.offset().top + element.height() - $(window).height() + setTop;
+ tmp2 = $('').height(1200).appendTo("body");
});
- describe('Sticky.stick', function () {
- beforeEach(function () {
- tmp1 = $('').height(1200).prependTo("body");
- element = $('test
');
- element.appendTo('body');
- elementTop = element.offset().top - setTop;
- elementBottom = element.offset().top + element.height() - $(window).height() + setTop;
- tmp2 = $('').height(1200).appendTo("body");
- });
+ afterEach(function () {
+ tmp1.remove();
+ tmp2.remove();
+ element.remove();
+ element = null;
+ $('body').css('height', '');
+ $(document).off('scroll');
+ $(document).scrollTop(0);
+ });
+
+ it('返回实例对象', function () {
+ var obj = Sticky.stick(element, setTop);
+ expect(obj.destroy).to.be.a('function');
+ });
+
+ it('同一个接口', function () {
+ expect(Sticky).to.be.a('function');
+ expect(Sticky).to.be(Sticky.stick);
+ });
+
+ it('默认的 top 值', function () {
+ var obj = Sticky.stick(element);
+ expect(obj.position.top).to.be(0);
+ });
+
+ it('destroy 方法', function () {
+ var obj = Sticky.stick(element);
+ expect(element.data('bind-sticked')).to.be(true);
+ obj.destroy();
+ expect(element.data('bind-sticked')).to.be(false);
+ });
- afterEach(function () {
- tmp1.remove();
- tmp2.remove();
- element.remove();
- element = null;
- $('body').css('height', '');
- $(document).off('scroll');
- $(document).scrollTop(0);
- });
-
- it('返回实例对象', function () {
- var obj = Sticky.stick(element, setTop);
- expect(obj.destroy).to.be.a('function');
- });
-
- it('同一个接口', function () {
- expect(Sticky).to.be.a('function');
- expect(Sticky).to.be(Sticky.stick);
- });
-
- it('默认的 top 值', function () {
- var obj = Sticky.stick(element);
- expect(obj.position.top).to.be(0);
- });
-
- it('destroy 方法', function () {
- var obj = Sticky.stick(element);
- expect(element.data('bind-sticked')).to.be(true);
+ it('滚动了一像素', function (done) {
+ var originPosition = element.css('position');
+ var obj = Sticky.stick(element, setTop);
+ $(document).scrollTop(1);
+
+ setTimeout(function () {
+ if (isPositionStickySupported) {
+ expect(element.css('position').indexOf("sticky") !== -1).to.be(true);
+ } else {
+ expect(element.css('position')).to.be(originPosition);
+ }
+ done();
obj.destroy();
- expect(element.data('bind-sticked')).to.be(false);
- });
+ }, timeout);
+ });
- it('滚动了一像素', function (done) {
- var originPosition = element.css('position');
- var obj = Sticky.stick(element, setTop);
- $(document).scrollTop(1);
+ it('滚动到差一像素', function (done) {
+ var originPosition = element.css('position');
+ var obj = Sticky.stick(element, setTop);
+ $(document).scrollTop(elementTop - 1);
+
+ setTimeout(function () {
+ if (isPositionStickySupported) {
+ expect(element.css('position').indexOf("sticky") !== -1).to.be(true);
+ } else {
+ expect(element.css('position')).to.be(originPosition);
+ }
+ done();
+ obj.destroy();
+ }, timeout);
+ });
- setTimeout(function () {
- if (isPositionStickySupported) {
- expect(element.css('position').indexOf("sticky") !== -1).to.be(true);
- } else {
- expect(element.css('position')).to.be(originPosition);
- }
- done();
- obj.destroy();
- }, timeout);
- });
+ it('滚动到元素临界位置', function (done) {
+ var obj = Sticky.stick(element, setTop);
+ $(document).scrollTop(elementTop);
+
+ setTimeout(function () {
+ if (isPositionStickySupported) {
+ expect(element.css('position').indexOf("sticky") !== -1).to.be(true);
+ } else if (isPositionFixedSupported) {
+ expect(element.css('position')).to.be("fixed");
+ } else {
+ expect(element.css('position')).to.be("absolute");
+ }
+ done();
+ obj.destroy();
+ }, timeout);
+ });
- it('滚动到差一像素', function (done) {
- var originPosition = element.css('position');
- var obj = Sticky.stick(element, setTop);
- $(document).scrollTop(elementTop - 1);
+ it('滚动到元素临界位置多一像素', function (done) {
+ var obj = Sticky.stick(element, setTop);
+ $(document).scrollTop(elementTop + 1);
+
+ setTimeout(function () {
+ if (isPositionStickySupported) {
+ expect(element.css('position').indexOf("sticky") !== -1).to.be(true);
+ } else if (isPositionFixedSupported) {
+ expect(element.css('position')).to.be("fixed");
+ } else {
+ expect(element.css('position')).to.be("absolute");
+ }
+ done();
+ obj.destroy();
+ }, timeout);
- setTimeout(function () {
- if (isPositionStickySupported) {
- expect(element.css('position').indexOf("sticky") !== -1).to.be(true);
- } else {
- expect(element.css('position')).to.be(originPosition);
- }
- done();
- obj.destroy();
- }, timeout);
- });
+ });
- it('滚动到元素临界位置', function (done) {
- var obj = Sticky.stick(element, setTop);
- $(document).scrollTop(elementTop);
+ it('滚动到元素临界位置多300像素', function (done) {
+ var obj = Sticky.stick(element, setTop);
+ $(document).scrollTop(elementTop + 300);
+
+ setTimeout(function () {
+ if (isPositionStickySupported) {
+ expect(element.css('position').indexOf("sticky") !== -1).to.be(true);
+ } else if (isPositionFixedSupported) {
+ expect(element.css('position')).to.be("fixed");
+ } else {
+ expect(element.css('position')).to.be("absolute");
+ }
+ done();
+ obj.destroy();
+ }, timeout);
+ });
- setTimeout(function () {
- if (isPositionStickySupported) {
- expect(element.css('position').indexOf("sticky") !== -1).to.be(true);
- } else if (isPositionFixedSupported) {
- expect(element.css('position')).to.be("fixed");
- } else {
- expect(element.css('position')).to.be("absolute");
- }
- done();
- obj.destroy();
- }, timeout);
- });
+ it('不可见元素', function (done) {
+ var obj = Sticky.stick(element, setTop);
+ element.hide();
+ $(document).scrollTop(elementTop + 300);
- it('滚动到元素临界位置多一像素', function (done) {
- var obj = Sticky.stick(element, setTop);
- $(document).scrollTop(elementTop + 1);
+ setTimeout(function () {
+ expect(element.css('position').indexOf("sticky") !== -1 || element.css('position') === "static").to.be(true);
+ done();
+ element.show();
+ obj.destroy();
+ }, timeout);
+ });
- setTimeout(function () {
- if (isPositionStickySupported) {
- expect(element.css('position').indexOf("sticky") !== -1).to.be(true);
- } else if (isPositionFixedSupported) {
- expect(element.css('position')).to.be("fixed");
- } else {
- expect(element.css('position')).to.be("absolute");
- }
- done();
- obj.destroy();
- }, timeout);
+ it('非块级元素,不加占位元素,以减少复杂性', function (done) {
+ element.css('display', 'inline')
+ var obj = Sticky.stick(element, setTop);
+ $(document).scrollTop(elementTop + 300);
- });
+ setTimeout(function () {
+ expect(obj._placeholder).to.be(undefined);
+ done();
+ obj.destroy();
+ }, timeout);
+ });
- it('滚动到元素临界位置多300像素', function (done) {
- var obj = Sticky.stick(element, setTop);
- $(document).scrollTop(elementTop + 300);
+ it('stick 回调', function (done) {
+ var triggered = 0;
- setTimeout(function () {
- if (isPositionStickySupported) {
- expect(element.css('position').indexOf("sticky") !== -1).to.be(true);
- } else if (isPositionFixedSupported) {
- expect(element.css('position')).to.be("fixed");
- } else {
- expect(element.css('position')).to.be("absolute");
- }
- done();
- obj.destroy();
- }, timeout);
+ var obj = Sticky.stick(element, setTop, function(status) {
+ if (status) {
+ triggered = 1;
+ } else {
+ triggered = 2;
+ }
});
- it('不可见元素', function (done) {
- var obj = Sticky.stick(element, setTop);
- element.hide();
- $(document).scrollTop(elementTop + 300);
+ $(document).scrollTop(elementTop);
+
+ setTimeout(function () {
+ expect(triggered).to.be(1);
+ $(document).scrollTop(0);
setTimeout(function () {
- expect(element.css('position').indexOf("sticky") !== -1 || element.css('position') === "static").to.be(true);
+ expect(triggered).to.be(2);
done();
- element.show();
obj.destroy();
}, timeout);
- });
+ }, timeout);
+ });
- it('非块级元素,不加占位元素,以减少复杂性', function (done) {
- element.css('display', 'inline')
- var obj = Sticky.stick(element, setTop);
- $(document).scrollTop(elementTop + 300);
+ it('重复绑定', function (done) {
+ var triggered = 0;
- setTimeout(function () {
- expect(obj._placeholder).to.be(undefined);
- done();
- obj.destroy();
- }, timeout);
+ var obj1 = Sticky.stick(element, setTop, function(status) {
+ if (status) {
+ triggered = 1;
+ } else {
+ triggered = 2;
+ }
+ });
+ var obj2 = Sticky.stick(element, setTop, function(status) {
+ if (status) {
+ triggered = 3;
+ } else {
+ triggered = 4;
+ }
});
- it('stick 回调', function (done) {
- var triggered = 0;
-
- var obj = Sticky.stick(element, setTop, function(status) {
- if (status) {
- triggered = 1;
- } else {
- triggered = 2;
- }
- });
+ $(document).scrollTop(elementTop);
- $(document).scrollTop(elementTop);
+ setTimeout(function () {
+ expect(triggered).to.be(1);
- setTimeout(function () {
- expect(triggered).to.be(1);
- $(document).scrollTop(0);
+ done();
- setTimeout(function () {
- expect(triggered).to.be(2);
- done();
- obj.destroy();
- }, timeout);
- }, timeout);
- });
+ obj1.destroy();
+ }, timeout);
+ });
- it('重复绑定', function (done) {
- var triggered = 0;
-
- var obj1 = Sticky.stick(element, setTop, function(status) {
- if (status) {
- triggered = 1;
- } else {
- triggered = 2;
- }
- });
- var obj2 = Sticky.stick(element, setTop, function(status) {
- if (status) {
- triggered = 3;
- } else {
- triggered = 4;
- }
- });
-
- $(document).scrollTop(elementTop);
+ it("不支持 position: sticky 的情况", function(done) {
+ Sticky.isPositionStickySupported = false;
- setTimeout(function () {
- expect(triggered).to.be(1);
+ var obj = Sticky.stick(element, setTop);
+ $(document).scrollTop(elementTop + 300);
- done();
+ setTimeout(function () {
+ expect(element.css('position')).to.be(isPositionFixedSupported ? 'fixed' : 'absolute');
+ done();
+ obj.destroy();
+ }, timeout);
+ });
- obj1.destroy();
- }, timeout);
- });
+ it("强制支持 position: sticky 的情况", function(done) {
+ Sticky.isPositionStickySupported = true;
- it("不支持 position: sticky 的情况", function(done) {
- Sticky.isPositionStickySupported = false;
+ var obj = Sticky.stick(element, setTop);
+ $(document).scrollTop(elementTop + 300);
- var obj = Sticky.stick(element, setTop);
- $(document).scrollTop(elementTop + 300);
+ setTimeout(function () {
+ expect(element.css('position').indexOf("sticky") !== -1 || element.css('position') === "static").to.be(true);
+ $(document).scrollTop(0);
- setTimeout(function () {
- expect(element.css('position')).to.be(isPositionFixedSupported ? 'fixed' : 'absolute');
+ setTimeout(function() {
+ expect(element.css('position').indexOf("sticky") !== -1 || element.css('position') === "static").to.be(true);
done();
obj.destroy();
}, timeout);
- });
-
- it("强制支持 position: sticky 的情况", function(done) {
- Sticky.isPositionStickySupported = true;
-
- var obj = Sticky.stick(element, setTop);
- $(document).scrollTop(elementTop + 300);
-
- setTimeout(function () {
- expect(element.css('position').indexOf("sticky") !== -1 || element.css('position') === "static").to.be(true);
- $(document).scrollTop(0);
+ }, timeout);
+ });
- setTimeout(function() {
- expect(element.css('position').indexOf("sticky") !== -1 || element.css('position') === "static").to.be(true);
- done();
- obj.destroy();
- }, timeout);
- }, timeout);
- });
+ it("不支持 position: sticky 且不支持 position: fixed 的情况", function(done) {
+ Sticky.isPositionStickySupported = false;
- it("不支持 position: sticky 且不支持 position: fixed 的情况", function(done) {
- Sticky.isPositionStickySupported = false;
+ Sticky.isPositionFixedSupported = false;
- Sticky.isPositionFixedSupported = false;
+ var obj = Sticky.stick(element, setTop);
+ $(document).scrollTop(elementTop + 300);
- var obj = Sticky.stick(element, setTop);
- $(document).scrollTop(elementTop + 300);
+ setTimeout(function () {
+ expect(element.css('position')).to.be('absolute');
+ $(document).scrollTop(0);
setTimeout(function () {
- expect(element.css('position')).to.be('absolute');
- $(document).scrollTop(0);
-
- setTimeout(function () {
- expect(element.css('position') === "static").to.be(true);
+ expect(element.css('position') === "static").to.be(true);
- done();
- obj.destroy();
+ done();
+ obj.destroy();
- }, timeout);
}, timeout);
+ }, timeout);
+ });
+
+ it('手工调用 adjust', function (done) {
+ var triggered = 0;
+
+ var obj = Sticky.stick(element, setTop, function(status) {
+ if (status) {
+ triggered = 1;
+ } else {
+ triggered = 2;
+ }
});
- it('手工调用 adjust', function (done) {
- var triggered = 0;
+ $(document).scrollTop(elementTop);
- var obj = Sticky.stick(element, setTop, function(status) {
- if (status) {
- triggered = 1;
- } else {
- triggered = 2;
- }
- });
+ setTimeout(function () {
+ expect(triggered).to.be(1);
- $(document).scrollTop(elementTop);
+ tmp1.css('height', tmpHeight + 200);
+ obj.adjust();
+ expect(triggered).to.be(2);
+ $(document).scrollTop(elementTop + 200);
setTimeout(function () {
expect(triggered).to.be(1);
-
- tmp1.css('height', tmpHeight + 200);
- obj.adjust();
- expect(triggered).to.be(2);
- $(document).scrollTop(elementTop + 200);
-
- setTimeout(function () {
- expect(triggered).to.be(1);
- done();
- obj.destroy();
- }, timeout);
+ done();
+ obj.destroy();
}, timeout);
+ }, timeout);
+ });
+
+ it('set top and bottom', function(done) {
+ var triggered = 0;
+
+ var obj = Sticky.stick(element, {
+ top: setTop,
+ bottom: setTop
+ }, function(status) {
+ if (status) {
+ triggered = 1;
+ } else {
+ triggered = 2;
+ }
});
+ $(document).scrollTop(elementTop);
- it('set top and bottom', function(done) {
- var triggered = 0;
-
- var obj = Sticky.stick(element, {
- top: setTop,
- bottom: setTop
- }, function(status) {
- if (status) {
- triggered = 1;
- } else {
- triggered = 2;
- }
- });
- $(document).scrollTop(elementTop);
+ setTimeout(function() {
+ expect(triggered).to.be(1);
+ $(document).scrollTop(elementBottom + 1);
setTimeout(function() {
- expect(triggered).to.be(1);
+ expect(triggered).to.be(2);
- $(document).scrollTop(elementBottom + 1);
+ $(document).scrollTop(elementBottom);
setTimeout(function() {
- expect(triggered).to.be(2);
-
- $(document).scrollTop(elementBottom);
- setTimeout(function() {
- expect(triggered).to.be(1);
- done();
- obj.destroy();
- }, timeout);
+ expect(triggered).to.be(1);
+ done();
+ obj.destroy();
}, timeout);
}, timeout);
- });
+ }, timeout);
+ });
- it('window resize', function(done) {
- var obj = Sticky.stick(element, setTop);
- $(document).scrollTop(elementTop);
- $(window).resize();
+ it('window resize', function(done) {
+ var obj = Sticky.stick(element, setTop);
+ $(document).scrollTop(elementTop);
+ $(window).resize();
- setTimeout(function() {
- done();
- }, 200);
- });
+ setTimeout(function() {
+ done();
+ }, 200);
});
});