Repository: iamvdo/stickyElements
Branch: master
Commit: 185064af6f8f
Files: 12
Total size: 28.0 KB
Directory structure:
gitextract_ihm_xnm8/
├── .gitignore
├── .npmignore
├── README.md
├── build.js
├── dist/
│ ├── stickyelements-animate.js
│ └── stickyelements.js
├── package.json
├── src/
│ ├── StickyElement.js
│ └── stickyElements.js
└── test/
├── index.html
├── test.html
└── test.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
node_modules
================================================
FILE: .npmignore
================================================
node_modules
demo
test
.gitignore
build.js
================================================
FILE: README.md
================================================
# Sticky Elements
Everything can stick. Just because.
[Demo](http://design.iamvdo.me/stickyElements)
## Getting started
`npm install stickyelements` and insert `dist/stickyelements-animate.js` (or build your own bundle using `src` files)
Then, stick elements!
```javascript
stickyElements('.item', {
stickiness: 5,
duration: 450
});
```
## Arguments
### CSS selector
* Elements that will stick to your mouse
### Options
* `stickiness` [Integer, Object]: How long elements remain stick to your mouse. If integer, apply same `x` and `y` values. If object, can contain `x` and/or `y` key. Integer between 0 and 10. (Default: `3`)
* `duration` [Integer]: Duration in milliseconds of animation (using [animateplus](https://github.com/bendc/animateplus). (Default: `450`)
* `pointer` [Boolean]: Enable Pointer Events instead of Mouse Events. Elements will stick to mouse, touch and all input types (Default: `false`). Need [PEP polyfill](https://github.com/jquery/PEP) and `touch-action` attribute on each elements (follow PEP polyfill instructions).
================================================
FILE: build.js
================================================
var fs = require('fs');
var babel = require('rollup-plugin-babel');
var rollup = require('rollup');
var uglify = require('uglify-js');
var args = process.argv;
var packageFile = JSON.parse(fs.readFileSync('package.json', 'utf8'));
var version = packageFile.version;
var files = {
src: './src/stickyElements.js',
srcAnimate: './node_modules/animateplus/animate.min.js',
dist: './dist/stickyelements.js',
distAnimate: './dist/stickyelements-animate.js'
}
function minify (code) {
return uglify.minify(code, {fromString: true}).code;
}
function runBuild () {
fs.mkdir('./dist', (err) => {
rollup.rollup({
entry: files.src,
plugins: [ babel({presets: [ 'es2015-rollup' ]}) ]
}).then(function (bundle) {
var result = bundle.generate({
format: 'iife',
moduleName: 'stickyElements'
});
var code = minify(result.code);
fs.writeFile(files.dist, code, 'utf8');
fs.readFile(files.srcAnimate, 'utf8', (err, animate) => {
fs.writeFile(files.distAnimate, animate + code, 'utf8');
});
}, function (err) {
console.log(err);
});
});
}
runBuild();
if (args[2] && args[2] === '-w') {
fs.watchFile(files.src, runBuild);
fs.watchFile('./src/StickyElement.js', runBuild);
}
================================================
FILE: dist/stickyelements-animate.js
================================================
var animate=function(){function F(a){return Array.isArray(a)?a:Array.prototype.slice.call(a)}var k=function(a){var c=a.length;return function d(){for(var e=arguments.length,f=Array(e),g=0;g<e;g++)f[g]=arguments[g];return f.length<c?function(){for(var a=arguments.length,c=Array(a),e=0;e<a;e++)c[e]=arguments[e];return d.apply(void 0,f.concat(c))}:a.apply(void 0,f)}},r=function(){for(var a=arguments.length,c=Array(a),b=0;b<a;b++)c[b]=arguments[b];return function(a){return c.reduce(function(a,b){return b(a)},
a)}},t=function(a){return function(){return!a.apply(void 0,arguments)}},G={linear:function(a,c,b,d){return c+a/d*b},easeInQuad:function(a,c,b,d){return b*(a/=d)*a+c},easeInCubic:function(a,c,b,d){return b*(a/=d)*a*a+c},easeInQuart:function(a,c,b,d){return b*(a/=d)*a*a*a+c},easeInQuint:function(a,c,b,d){return b*(a/=d)*a*a*a*a+c},easeInSine:function(a,c,b,d){return-b*Math.cos(a/d*(Math.PI/2))+b+c},easeInExpo:function(a,c,b,d){return 0==a?c:b*Math.pow(2,10*(a/d-1))+c},easeInCirc:function(a,c,b,d){return-b*
(Math.sqrt(1-(a/=d)*a)-1)+c},easeInElastic:function(a,c,b,d){var e=4>=arguments.length||void 0===arguments[4]?500:arguments[4];if(0==a)return c;if(1==(a/=d))return c+b;var e=d*(1-Math.min(e,999)/1E3),f=b<Math.abs(b)?e/4:e/(2*Math.PI)*Math.asin(b/b);return-(b*Math.pow(2,10*--a)*Math.sin(2*(a*d-f)*Math.PI/e))+c},easeInBack:function(a,c,b,d){return b*(a/=d)*a*(2.70158*a-1.70158)+c},easeOutQuad:function(a,c,b,d){return-b*(a/=d)*(a-2)+c},easeOutCubic:function(a,c,b,d){return b*((a=a/d-1)*a*a+1)+c},easeOutQuart:function(a,
c,b,d){return-b*((a=a/d-1)*a*a*a-1)+c},easeOutQuint:function(a,c,b,d){return b*((a=a/d-1)*a*a*a*a+1)+c},easeOutSine:function(a,c,b,d){return b*Math.sin(a/d*(Math.PI/2))+c},easeOutExpo:function(a,c,b,d){return a==d?c+b:b*(-Math.pow(2,-10*a/d)+1)+c},easeOutCirc:function(a,c,b,d){return b*Math.sqrt(1-(a=a/d-1)*a)+c},easeOutElastic:function(a,c,b,d){var e=4>=arguments.length||void 0===arguments[4]?500:arguments[4];if(0==a)return c;if(1==(a/=d))return c+b;e=d*(1-Math.min(e,999)/1E3);return b*Math.pow(2,
-10*a)*Math.sin(2*(a*d-(b<Math.abs(b)?e/4:e/(2*Math.PI)*Math.asin(b/b)))*Math.PI/e)+b+c},easeOutBack:function(a,c,b,d){return b*((a=a/d-1)*a*(2.70158*a+1.70158)+1)+c},easeOutBounce:function(a,c,b,d){return(a/=d)<1/2.75?7.5625*b*a*a+c:a<2/2.75?b*(7.5625*(a-=1.5/2.75)*a+.75)+c:a<2.5/2.75?b*(7.5625*(a-=2.25/2.75)*a+.9375)+c:b*(7.5625*(a-=2.625/2.75)*a+.984375)+c},easeInOutQuad:function(a,c,b,d){return 1>(a/=d/2)?b/2*a*a+c:-b/2*(--a*(a-2)-1)+c},easeInOutCubic:function(a,c,b,d){return 1>(a/=d/2)?b/2*a*
a*a+c:b/2*((a-=2)*a*a+2)+c},easeInOutQuart:function(a,c,b,d){return 1>(a/=d/2)?b/2*a*a*a*a+c:-b/2*((a-=2)*a*a*a-2)+c},easeInOutQuint:function(a,c,b,d){return 1>(a/=d/2)?b/2*a*a*a*a*a+c:b/2*((a-=2)*a*a*a*a+2)+c},easeInOutSine:function(a,c,b,d){return-b/2*(Math.cos(Math.PI*a/d)-1)+c},easeInOutExpo:function(a,c,b,d){return 0==a?c:a==d?c+b:1>(a/=d/2)?b/2*Math.pow(2,10*(a-1))+c:b/2*(-Math.pow(2,-10*--a)+2)+c},easeInOutCirc:function(a,c,b,d){return 1>(a/=d/2)?-b/2*(Math.sqrt(1-a*a)-1)+c:b/2*(Math.sqrt(1-
(a-=2)*a)+1)+c},easeInOutElastic:function(a,c,b,d){var e=4>=arguments.length||void 0===arguments[4]?500:arguments[4];if(0==a)return c;if(2==(a/=d/2))return c+b;var e=d*(1-Math.min(e,999)/1E3)*1.5,f=b<Math.abs(b)?e/4:e/(2*Math.PI)*Math.asin(b/b);return 1>a?-.5*b*Math.pow(2,10*--a)*Math.sin(2*(a*d-f)*Math.PI/e)+c:b*Math.pow(2,-10*--a)*Math.sin(2*(a*d-f)*Math.PI/e)*.5+b+c},easeInOutBack:function(a,c,b,d){var e=1.70158;return 1>(a/=d/2)?b/2*a*a*(((e*=1.525)+1)*a-e)+c:b/2*((a-=2)*a*(((e*=1.525)+1)*a+e)+
2)+c}},y=function(a){return a[0]},H=function(a){return a.reduce(function(a,b){return a.concat(b)})},n=function(){return Array.prototype.includes?function(a,c){return a.includes(c)}:function(a,c){return a.some(function(a){return a===c})}}(),z=function(a){for(var c=arguments.length,b=Array(1<c?c-1:0),d=1;d<c;d++)b[d-1]=arguments[d];var e=H(b);return a.filter(function(a){return t(n)(e,a)})},q=function(){return Array.from?function(a){return Array.from(a.keys())}:function(a){var c=[];a.forEach(function(a,
d){return c.push(d)});return c}}(),I=function(){var a=function(a){var b=new Map;Object.keys(a).forEach(function(d){return b.set(d,a[d])});return b};return function(c){return c instanceof Map?c:a(c)}}(),h=function(){try{if(!(new Map((new Map).set(null,null))).size)throw Error();}catch(a){return function(a){var b=new Map;a.forEach(function(a,c){return b.set(c,a)});return b}}return function(a){return new Map(a)}}(),J=function(a){return/^#/.test(a)},A=function(a){return/^rgb/.test(a)},K=function(){var a=
function(a){return 7>a.length?a.split("").reduce(function(a,b){return a+b+b}):a},c=function(a){return a.match(/[\d\w]{2}/g).map(function(a){return parseInt(a,16)})};return function(b){if(A(b))return b;b=r(a,c)(b);return"rgb("+b[0]+", "+b[1]+", "+b[2]+")"}}(),B=function(a){a="string"==typeof a?/^[\#.]?[\w-]+$/.test(a)?"."==a[0]?document.getElementsByClassName(a.slice(1)):"#"==a[0]?document.getElementById(a.slice(1)):document.getElementsByTagName(a):document.querySelectorAll(a):a;return Array.isArray(a)?
a:a.nodeType?[a]:a instanceof NodeList||a instanceof HTMLCollection?[].concat(F(a)):a.get()},m=new Map;"el delay begin complete loop direction".split(" ").forEach(function(a){return m.set(a,null)});m.set("duration",1E3);m.set("easing","easeOutElastic");var L=function(){var a=q(m).filter(function(a){return m.get(a)}),c=function(b){return a.every(function(a){return b.has(a)})},b=function(b){var c=h(b);a.forEach(function(a){c.has(a)||c.set(a,m.get(a))});return c};return function(a){return c(a)?a:b(a)}}(),
M=function(){var a=k(function(a,b){return Array.isArray(a.get(b))}),c=function(b){return p(b).every(a(b))},b=function(b){return p(b).filter(t(a(b)))};return function(a){if(c(a))return a;var e=h(a);b(e).forEach(function(a){return e.set(a,[C.get(a),e.get(a)])});return e}}(),N=function(){var a=function(a){return/\D$/.test(a)},c=k(function(b,c){return a(c)||/scale/.test(b)?c:/rotate|skew/.test(b)?c+"deg":c+"px"}),b=function(b,c){return c.every(function(c){return b.get(c).every(a)})};return function(a){var e=
p(a).filter(u);if(b(a,e))return a;var f=h(a);e.forEach(function(b){return f.set(b,a.get(b).map(c(b)))});return f}}(),O=function(){var a=k(function(a,b){return a.get(b).some(J)}),c=function(b){return!D(b).some(a(b))},b=function(b){return D(b).filter(a(b))};return function(a){if(c(a))return a;var e=h(a);b(a).forEach(function(a){return e.set(a,e.get(a).map(K))});return e}}(),E=function(a){var c=h(a);v(a).forEach(function(a){return c.set(a,c.get(a).slice().reverse())});return c},P=r(I,L,M,N,O,function(a){var c=
h(a);c.set("el",B(a.get("el")));return c},function(a){return"reverse"==a.get("direction")?E(a):a}),v=function(){var a=q(m),c=function(b){return t(n)(a,b)};return function(a){return q(a).filter(c)}}(),R=function(){var a=r(y,A),c=k(function(b,c){var e=b.get(c).map(Q),f=e[0],g=e[1],e=new Map;e.set("prop",c);e.set("from",f);e.set("to",g);e.set("isTransformFunction",u(c));e.set("isColor",a(b.get(c)));/\d$/.test(b.get("easing"))?(f=b.get("easing").split(" "),g=f[1],e.set("easing",f[0]),e.set("frequency",
g)):e.set("easing",b.get("easing"));return e});return function(a,d){return v(a).map(c(a))}}(),p=function(){var a=function(a){return n(w,a)};return function(c){return q(c).filter(a)}}(),D=function(a){return z(v(a),p(a))},w="opacity translateX translateY scale rotate scaleX scaleY rotateX rotateY perspective skewX skewY translateZ rotateZ scaleZ".split(" "),C=new Map;w.forEach(function(a){return C.set(a,n(["opacity","scale","scaleX","scaleY"],a)?1:0)});var u=function(){var a=w.filter(function(a){return"opacity"!=
a});return function(c){return n(a,c)}}(),S=function(a){var c=p(a);if(c.length){var b=[];c.some(u)&&b.push("transform");n(c,"opacity")&&b.push("opacity");var d=b.join();a.get("el").forEach(function(a){a.style.willChange||(a.style.willChange=d)})}},T=function(a,c){return c.reduce(function(b,c,e){return b+a[e-1]+c})},Q=function(){var a=/-?\d*\.?\d+/g;return function(c){var b=new Map;b.set("digits",("string"==typeof c?c:String(c)).match(a).map(Number));b.set("others",("string"==typeof c?c:String(c)).split(a));
return b}}(),U=k(function(a,c,b){var d=b.get("to").get("digits").map(function(d,f){var g=b.get("from").get("digits")[f];if(g==d)return g;var h=d-g,g=G[b.get("easing")](c,g,h,a.get("duration"),b.get("frequency"));return b.get("isColor")?Math.round(g):g});return T(d,b.get("to").get("others"))}),V=k(function(a,c){var b=a.get(c.get("prop"));return y(b.slice(-1))}),W=function(){var a=void 0;return k(function(c,b,d){var e=void 0;c.forEach(function(a,c){a.get("isTransformFunction")?(e||(e=[]),e.push(a.get("prop")+
"("+b[c]+")")):"opacity"==a.get("prop")?d.style.opacity=b[c]:d.setAttribute(a.get("prop"),b[c])});e&&(a||(a="transform"in document.body.style?"transform":"-webkit-transform"),d.style[a]=e.join(" "))})}(),X=function(){var a=function(a,b){b.get("begin")&&b.get("begin")(b.get("el"));requestAnimationFrame(a)};return function(c,b){return b.get("delay")?setTimeout(function(){return a(c,b)},b.get("delay")):a(c,b)}}(),Y=function(a){return x(function(){if("alternate"==a.get("direction"))return E(a);if("reverse"==
a.get("direction")){var c=h(a);c["delete"]("direction");return c}return a}())},l=new Map,Z=function(){var a=0;return function(c){var b=a++,d=h(l);d.set(b,c);l=d;return b}}(),x=function(a){var c=P(a),b=R(c),d=Z(c.get("el")),e=new Map;S(c);X(function g(a){if(l.has(d)){e.has("start")||e.set("start",a);e.set("elapsed",a-e.get("start"));a=e.get("elapsed")<c.get("duration");var k=b.map(a?U(c,e.get("elapsed")):V(c));l.get(d).forEach(W(b,k));a?requestAnimationFrame(g):(a=h(l),a["delete"](d),l=a,c.get("complete")&&
c.get("complete")(c.get("el")),c.get("loop")&&Y(c))}},c)};x.stop=function(a){var c=B(a),b=h(l);b.forEach(function(a,e){var f=z(a,c);f.length?b.set(e,f):b["delete"](e)});l=b};return x}();"undefined"!=typeof module&&module.exports&&(module.exports=animate);var stickyElements=function(){"use strict";var t={};t.classCallCheck=function(t,s){if(!(t instanceof s))throw new TypeError("Cannot call a class as a function")},t.createClass=function(){function t(t,s){for(var i=0;i<s.length;i++){var e=s[i];e.enumerable=e.enumerable||!1,e.configurable=!0,"value"in e&&(e.writable=!0),Object.defineProperty(t,e.key,e)}}return function(s,i,e){return i&&t(s.prototype,i),e&&t(s,e),s}}();var s=function(){function s(i){var e=arguments.length<=1||void 0===arguments[1]?{}:arguments[1];t.classCallCheck(this,s),this.el=i,this.setOpts(e),this.setEvents()}return t.createClass(s,[{key:"setOpts",value:function(t){this.pointer=t.pointer,this.positions={},this.isGripped=!1,this.stickiness={},this.grip={x:3,y:4},this.duration=t.duration||450,this.setStickiness(t)}},{key:"setEvents",value:function(){var t=this,s=this.el,i=["enter","leave","move"];s._stickyEvents&&(i.map(function(i){t.pointer?s.removeEventListener("pointer"+i,s._stickyEvents[i],!1):s.removeEventListener("mouse"+i,s._stickyEvents[i],!1)}),s._stickyEvents=void 0),s._stickyEvents={enter:function(s){return t.onEnter(s)},leave:function(s){return t.onLeave(s)},move:function(s){return t.onMove(s)}},i.map(function(i){t.pointer?s.addEventListener("pointer"+i,s._stickyEvents[i],!1):s.addEventListener("mouse"+i,s._stickyEvents[i],!1)})}},{key:"setStickiness",value:function(t){var s={1:10,2:6.6,3:4.5,4:3.2,5:2.4,6:1.9,7:1.6,8:1.4,9:1.3,10:1.2,0:0},i={stickiness:{x:3,y:3}};(t.stickiness||0===t.stickiness)&&("number"==typeof t.stickiness&&(i.stickiness={x:t.stickiness,y:t.stickiness}),(t.stickiness.x||0===t.stickiness.x)&&(i.stickiness.x=t.stickiness.x),(t.stickiness.y||0===t.stickiness.y)&&(i.stickiness.y=t.stickiness.y)),this.stickiness.x=s[Math.min(10,i.stickiness.x)],this.stickiness.y=s[Math.min(10,i.stickiness.y)]}},{key:"getPositions",value:function(t,s){var i=0!==this.stickiness.x?t/this.stickiness.x:0,e=0!==this.stickiness.y?s/this.stickiness.y:0;return{posx:i,posy:e}}},{key:"onEnter",value:function(t){var s=this.el,i=s.offsetWidth,e=s.offsetHeight,n=s.offsetLeft,o=s.offsetTop,r=window.pageYOffset||document.documentElement.scrollTop,a={width:i,height:e,centerx:n+i/2,centery:o+e/2-r};this.positions=a}},{key:"onLeave",value:function(t){if(this.lastGripped){var s=(new Date).getTime();if(s-this.lastGripped<30)return}var i=this.el;animate.stop(i);var e=this.getPositions(this.positions.deltax,this.positions.deltay),n=e.posx,o=e.posy;this.isGripped&&(this.lastGripped=(new Date).getTime(),animate({el:i,translateX:[n,0],translateY:[o,0],duration:this.duration})),this.isGripped=!1}},{key:"onMove",value:function(t){var s=this.el;animate.stop(s);var i=t.clientX,e=t.clientY,n={x:Math.abs(this.positions.deltax)<this.positions.width/this.grip.x,y:Math.abs(this.positions.deltay)<this.positions.height/this.grip.y};if(n.x&&n.y&&(this.isGripped=!0),this.positions.deltax=-(this.positions.centerx-i),this.positions.deltay=-(this.positions.centery-e),this.isGripped){var o=this.getPositions(this.positions.deltax,this.positions.deltay),r=o.posx,a=o.posy;s.style.transform="translate3d("+r+"px, "+a+"px, 0)"}}}]),s}(),i=function(){return function(t,i){for(var e=[],n=[].slice.call(document.querySelectorAll(t)),o=0;o<n.length;o++)e.push(new s(n[o],i));return e}}();return i}();
================================================
FILE: dist/stickyelements.js
================================================
var stickyElements=function(){"use strict";var t={};t.classCallCheck=function(t,s){if(!(t instanceof s))throw new TypeError("Cannot call a class as a function")},t.createClass=function(){function t(t,s){for(var i=0;i<s.length;i++){var e=s[i];e.enumerable=e.enumerable||!1,e.configurable=!0,"value"in e&&(e.writable=!0),Object.defineProperty(t,e.key,e)}}return function(s,i,e){return i&&t(s.prototype,i),e&&t(s,e),s}}();var s=function(){function s(i){var e=arguments.length<=1||void 0===arguments[1]?{}:arguments[1];t.classCallCheck(this,s),this.el=i,this.setOpts(e),this.setEvents()}return t.createClass(s,[{key:"setOpts",value:function(t){this.pointer=t.pointer,this.positions={},this.isGripped=!1,this.stickiness={},this.grip={x:3,y:4},this.duration=t.duration||450,this.setStickiness(t)}},{key:"setEvents",value:function(){var t=this,s=this.el,i=["enter","leave","move"];s._stickyEvents&&(i.map(function(i){t.pointer?s.removeEventListener("pointer"+i,s._stickyEvents[i],!1):s.removeEventListener("mouse"+i,s._stickyEvents[i],!1)}),s._stickyEvents=void 0),s._stickyEvents={enter:function(s){return t.onEnter(s)},leave:function(s){return t.onLeave(s)},move:function(s){return t.onMove(s)}},i.map(function(i){t.pointer?s.addEventListener("pointer"+i,s._stickyEvents[i],!1):s.addEventListener("mouse"+i,s._stickyEvents[i],!1)})}},{key:"setStickiness",value:function(t){var s={1:10,2:6.6,3:4.5,4:3.2,5:2.4,6:1.9,7:1.6,8:1.4,9:1.3,10:1.2,0:0},i={stickiness:{x:3,y:3}};(t.stickiness||0===t.stickiness)&&("number"==typeof t.stickiness&&(i.stickiness={x:t.stickiness,y:t.stickiness}),(t.stickiness.x||0===t.stickiness.x)&&(i.stickiness.x=t.stickiness.x),(t.stickiness.y||0===t.stickiness.y)&&(i.stickiness.y=t.stickiness.y)),this.stickiness.x=s[Math.min(10,i.stickiness.x)],this.stickiness.y=s[Math.min(10,i.stickiness.y)]}},{key:"getPositions",value:function(t,s){var i=0!==this.stickiness.x?t/this.stickiness.x:0,e=0!==this.stickiness.y?s/this.stickiness.y:0;return{posx:i,posy:e}}},{key:"onEnter",value:function(t){var s=this.el,i=s.offsetWidth,e=s.offsetHeight,n=s.offsetLeft,o=s.offsetTop,r=window.pageYOffset||document.documentElement.scrollTop,a={width:i,height:e,centerx:n+i/2,centery:o+e/2-r};this.positions=a}},{key:"onLeave",value:function(t){if(this.lastGripped){var s=(new Date).getTime();if(s-this.lastGripped<30)return}var i=this.el;animate.stop(i);var e=this.getPositions(this.positions.deltax,this.positions.deltay),n=e.posx,o=e.posy;this.isGripped&&(this.lastGripped=(new Date).getTime(),animate({el:i,translateX:[n,0],translateY:[o,0],duration:this.duration})),this.isGripped=!1}},{key:"onMove",value:function(t){var s=this.el;animate.stop(s);var i=t.clientX,e=t.clientY,n={x:Math.abs(this.positions.deltax)<this.positions.width/this.grip.x,y:Math.abs(this.positions.deltay)<this.positions.height/this.grip.y};if(n.x&&n.y&&(this.isGripped=!0),this.positions.deltax=-(this.positions.centerx-i),this.positions.deltay=-(this.positions.centery-e),this.isGripped){var o=this.getPositions(this.positions.deltax,this.positions.deltay),r=o.posx,a=o.posy;s.style.transform="translate3d("+r+"px, "+a+"px, 0)"}}}]),s}(),i=function(){return function(t,i){for(var e=[],n=[].slice.call(document.querySelectorAll(t)),o=0;o<n.length;o++)e.push(new s(n[o],i));return e}}();return i}();
================================================
FILE: package.json
================================================
{
"name": "stickyelements",
"version": "2.2.1",
"description": "Everything sticks. Just because.",
"main": "dist/stickyelements-animate.js",
"repository": {
"type": "git",
"url": "https://github.com/iamvdo/stickyElements.git"
},
"author": "Vincent De Oliveira <vincent@iamvdo.me>",
"license": "MIT",
"scripts": {
"build": "node ./build.js",
"watch": "node ./build.js -w"
},
"devDependencies": {
"animateplus": "^1.0.0",
"babel-preset-es2015-rollup": "^1.1.1",
"mocha": "^2.0.0",
"rollup": "^0.25.2",
"rollup-plugin-babel": "^2.3.9",
"uglify-js": "^2.6.1"
}
}
================================================
FILE: src/StickyElement.js
================================================
export default class StickyElement {
constructor (el, opts = {}) {
this.el = el;
this.setOpts(opts);
this.setEvents();
}
setOpts (opts) {
this.pointer = opts.pointer;
this.positions = {};
this.isGripped = false;
this.stickiness = {};
this.grip = {x: 3, y: 4};
this.duration = opts.duration || 450;
this.setStickiness(opts);
}
setEvents () {
let el = this.el;
const events = ['enter', 'leave', 'move'];
// prevent events to be registered multiple times
if (el._stickyEvents) {
events.map(e => {
if (this.pointer) {
el.removeEventListener('pointer' + e, el._stickyEvents[e], false);
} else {
el.removeEventListener('mouse' + e, el._stickyEvents[e], false);
}
});
el._stickyEvents = undefined;
}
el._stickyEvents = {
enter: (e) => this.onEnter(e),
leave: (e) => this.onLeave(e),
move: (e) => this.onMove(e)
};
events.map(e => {
if (this.pointer) {
el.addEventListener('pointer' + e, el._stickyEvents[e], false);
} else {
el.addEventListener('mouse' + e, el._stickyEvents[e], false);
}
});
}
setStickiness (opts) {
const forces = {
1: 10.0,
2: 6.6,
3: 4.5,
4: 3.2,
5: 2.4,
6: 1.9,
7: 1.6,
8: 1.4,
9: 1.3,
10: 1.2,
0: 0.0
};
let opt = {stickiness: {x: 3, y: 3}};
// if no options specified
if (opts.stickiness || opts.stickiness === 0) {
if (typeof opts.stickiness === "number") {
opt.stickiness = {x: opts.stickiness, y: opts.stickiness};
}
if (opts.stickiness.x || opts.stickiness.x === 0) {
opt.stickiness.x = opts.stickiness.x;
}
if (opts.stickiness.y || opts.stickiness.y === 0) {
opt.stickiness.y = opts.stickiness.y;
}
}
this.stickiness.x = forces[Math.min(10, opt.stickiness.x)];
this.stickiness.y = forces[Math.min(10, opt.stickiness.y)];
}
getPositions (deltax, deltay) {
const posx = (this.stickiness.x !== 0) ? deltax / this.stickiness.x : 0;
const posy = (this.stickiness.y !== 0) ? deltay / this.stickiness.y : 0;
return {posx, posy};
}
onEnter (event) {
const {offsetWidth, offsetHeight, offsetLeft, offsetTop} = this.el;
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const positions = {
width: offsetWidth,
height: offsetHeight,
centerx: offsetLeft + (offsetWidth / 2),
centery: offsetTop + (offsetHeight / 2) - scrollTop
};
this.positions = positions;
}
onLeave (event) {
// prevent mouseleave event to be triggered twice by 30ms
if (this.lastGripped) {
const now = new Date().getTime();
if (now - this.lastGripped < 30) {
return;
}
}
const element = this.el;
animate.stop(element);
const {posx, posy} = this.getPositions(this.positions.deltax, this.positions.deltay);
if (this.isGripped) {
this.lastGripped = new Date().getTime();
animate({
el: element,
translateX: [posx, 0],
translateY: [posy, 0],
duration: this.duration
});
}
this.isGripped = false;
}
onMove (event) {
const element = this.el;
animate.stop(element);
const {clientX, clientY} = event;
const isGrip = {
x: Math.abs(this.positions.deltax) < (this.positions.width / this.grip.x),
y: Math.abs(this.positions.deltay) < (this.positions.height / this.grip.y)
};
if (isGrip.x && isGrip.y) {
this.isGripped = true;
}
this.positions.deltax = -(this.positions.centerx - clientX);
this.positions.deltay = -(this.positions.centery - clientY);
if (this.isGripped) {
const {posx, posy} = this.getPositions(this.positions.deltax, this.positions.deltay);
element.style.transform = 'translate3d(' + posx + 'px, ' + posy + 'px, 0)';
}
}
}
================================================
FILE: src/stickyElements.js
================================================
import StickyElement from './StickyElement';
export default (() => {
return (selector, opts) => {
const stickyElementsTab = [];
const elements = [].slice.call(document.querySelectorAll(selector));
for (let i = 0; i < elements.length; i++) {
stickyElementsTab.push(new StickyElement(elements[i], opts));
};
return stickyElementsTab;
};
})();
================================================
FILE: test/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Live test</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
a, h1 span {
display: inline-block;
}
button {
padding: 2em;
font-size: 2em;
touch-action: none;
}
</style>
</head>
<body>
<h1><span touch-action="none">Sticky</span> Elements Playground</h1>
<p>This should be a <a href="#" touch-action="none">sticky link</a>. And another <a href="http://twitter.com/iamvdo">one</a></p>
<button touch-action="none">Big Fat Touch Button</button>
<script src="https://code.jquery.com/pep/0.4.1/pep.js"></script>
<script src="../dist/stickyelements-animate.js"></script>
<script>
stickyElements('a, button, h1 span', {stickiness: 5, pointer: true});
</script>
</body>
</html>
================================================
FILE: test/test.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tests</title>
<link rel="stylesheet" href="https://npmcdn.com/mocha@2.3.4/mocha.css">
</head>
<body>
<div id="mocha"></div>
<a href="#" class="mocha" style="display:none">Mocha</a>
<a href="#" class="multiple" style="display:none">Mocha</a>
<a href="#" class="multiple" style="display:none">Mocha</a>
<script src="https://npmcdn.com/jquery@2.1.4/dist/jquery.min.js"></script>
<script src="https://npmcdn.com/expect.js@0.3.1/index.js"></script>
<script src="https://npmcdn.com/mocha@2.3.4/mocha.js"></script>
<script src="../dist/stickyelements-animate.js"></script>
<script>mocha.setup('bdd')</script>
<script src="test.js"></script>
<script>
mocha.checkLeaks();
mocha.globals(['jQuery']);
mocha.run();
</script>
</body>
</html>
================================================
FILE: test/test.js
================================================
describe('stickyElements', function() {
describe('Lib', function () {
it('should set one stickyElements', function () {
var se = stickyElements('.mocha');
expect(se.length).to.eql(1);
});
it('should set multiple stickyElements', function () {
var se = stickyElements('.multiple');
expect(se.length).to.eql(2);
});
it('should create stickyElements instance', function () {
var se = stickyElements('.multiple');
for (var i = 0; i < se.length; i++) {
expect(se[i]).to.have.keys('el', 'stickiness');
expect(se[i].el).to.be.an(HTMLElement);
};
});
});
describe('Options', function () {
it('should set default options', function () {
var se = stickyElements('.mocha');
var stickiness = se[0].stickiness;
expect(stickiness).to.eql({x: 4.5, y: 4.5});
});
it('should set default options to multiple elements', function () {
var se = stickyElements('.multiple');
for (var i = 0; i < se.length; i++) {
var stickiness = se[i].stickiness;
expect(stickiness).to.eql({x: 4.5, y: 4.5});
};
});
it('should set default options to multiple elements with options', function () {
var se = stickyElements('.multiple', {});
for (var i = 0; i < se.length; i++) {
var stickiness = se[i].stickiness;
expect(stickiness).to.eql({x: 4.5, y: 4.5});
};
});
it('should overidde options', function () {
var se = stickyElements('.mocha', {stickiness: {x: 2, y: 4}});
var stickiness = se[0].stickiness;
expect(stickiness).to.eql({x: 6.6, y: 3.2});
});
it('should overidde only X option', function () {
var se = stickyElements('.mocha', {stickiness: {x: 2}});
var stickiness = se[0].stickiness;
expect(stickiness).to.eql({x: 6.6, y: 4.5});
});
it('should overidde only Y option', function () {
var se = stickyElements('.mocha', {stickiness: {y: 4}});
var stickiness = se[0].stickiness;
expect(stickiness).to.eql({x: 4.5, y: 3.2});
});
it('should accept integer', function () {
var se = stickyElements('.mocha', {stickiness: 2});
var stickiness = se[0].stickiness;
expect(stickiness).to.eql({x: 6.6, y: 6.6});
});
it('should accept 0', function () {
var se = stickyElements('.mocha', {stickiness: 0});
var stickiness = se[0].stickiness;
expect(stickiness).to.eql({x: 0.0, y: 0.0});
});
it('should accept 0, only X', function () {
var se = stickyElements('.mocha', {stickiness: {x: 0}});
var stickiness = se[0].stickiness;
expect(stickiness).to.eql({x: 0.0, y: 4.5});
});
it('should accept 0, only Y', function () {
var se = stickyElements('.mocha', {stickiness: {y: 0}});
var stickiness = se[0].stickiness;
expect(stickiness).to.eql({x: 4.5, y: 0.0});
});
it('should limit to 10', function () {
var se = stickyElements('.mocha', {stickiness: 12});
var stickiness = se[0].stickiness;
expect(stickiness).to.eql({x: 1.2, y: 1.2});
});
});
});
gitextract_ihm_xnm8/
├── .gitignore
├── .npmignore
├── README.md
├── build.js
├── dist/
│ ├── stickyelements-animate.js
│ └── stickyelements.js
├── package.json
├── src/
│ ├── StickyElement.js
│ └── stickyElements.js
└── test/
├── index.html
├── test.html
└── test.js
SYMBOL INDEX (16 symbols across 4 files)
FILE: build.js
function minify (line 18) | function minify (code) {
function runBuild (line 22) | function runBuild () {
FILE: dist/stickyelements-animate.js
function F (line 1) | function F(a){return Array.isArray(a)?a:Array.prototype.slice.call(a)}
function t (line 20) | function t(t,s){for(var i=0;i<s.length;i++){var e=s[i];e.enumerable=e.en...
function s (line 20) | function s(i){var e=arguments.length<=1||void 0===arguments[1]?{}:argume...
FILE: dist/stickyelements.js
function t (line 1) | function t(t,s){for(var i=0;i<s.length;i++){var e=s[i];e.enumerable=e.en...
function s (line 1) | function s(i){var e=arguments.length<=1||void 0===arguments[1]?{}:argume...
FILE: src/StickyElement.js
class StickyElement (line 1) | class StickyElement {
method constructor (line 3) | constructor (el, opts = {}) {
method setOpts (line 9) | setOpts (opts) {
method setEvents (line 19) | setEvents () {
method setStickiness (line 48) | setStickiness (opts) {
method getPositions (line 79) | getPositions (deltax, deltay) {
method onEnter (line 85) | onEnter (event) {
method onLeave (line 97) | onLeave (event) {
method onMove (line 122) | onMove (event) {
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (30K chars).
[
{
"path": ".gitignore",
"chars": 13,
"preview": "node_modules\n"
},
{
"path": ".npmignore",
"chars": 42,
"preview": "node_modules\ndemo\ntest\n.gitignore\nbuild.js"
},
{
"path": "README.md",
"chars": 1060,
"preview": "# Sticky Elements\n\nEverything can stick. Just because.\n\n[Demo](http://design.iamvdo.me/stickyElements)\n\n## Getting start"
},
{
"path": "build.js",
"chars": 1288,
"preview": "var fs = require('fs');\nvar babel = require('rollup-plugin-babel');\nvar rollup = require('rollup');\nvar uglify = requir"
},
{
"path": "dist/stickyelements-animate.js",
"chars": 13214,
"preview": "var animate=function(){function F(a){return Array.isArray(a)?a:Array.prototype.slice.call(a)}var k=function(a){var c=a.l"
},
{
"path": "dist/stickyelements.js",
"chars": 3281,
"preview": "var stickyElements=function(){\"use strict\";var t={};t.classCallCheck=function(t,s){if(!(t instanceof s))throw new TypeEr"
},
{
"path": "package.json",
"chars": 623,
"preview": "{\n \"name\": \"stickyelements\",\n \"version\": \"2.2.1\",\n \"description\": \"Everything sticks. Just because.\",\n \"main\": \"dist"
},
{
"path": "src/StickyElement.js",
"chars": 3985,
"preview": "export default class StickyElement {\n\n constructor (el, opts = {}) {\n this.el = el;\n this.setOpts(opts);\n this"
},
{
"path": "src/stickyElements.js",
"chars": 372,
"preview": "import StickyElement from './StickyElement';\n\nexport default (() => {\n return (selector, opts) => {\n const stickyEle"
},
{
"path": "test/index.html",
"chars": 820,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>Live test</title>\n <meta name=\"viewport\" cont"
},
{
"path": "test/test.html",
"chars": 842,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>Tests</title>\n <link rel=\"stylesheet\" href=\"h"
},
{
"path": "test/test.js",
"chars": 3110,
"preview": "describe('stickyElements', function() {\n describe('Lib', function () {\n it('should set one stickyElements', function"
}
]
About this extraction
This page contains the full source code of the iamvdo/stickyElements GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (28.0 KB), approximately 9.6k tokens, and a symbol index with 16 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.