1/** 2 * main.js 3 * http://www.codrops.com 4 * 5 * Licensed under the MIT license. 6 * http://www.opensource.org/licenses/mit-license.php 7 * 8 * Copyright 2015, Codrops 9 * http://www.codrops.com 10 */ 11; (function (window) { 12 13 'use strict'; 14 15 var support = { animations: Modernizr.cssanimations }, 16 animEndEventNames = { 'WebkitAnimation': 'webkitAnimationEnd', 'OAnimation': 'oAnimationEnd', 'msAnimation': 'MSAnimationEnd', 'animation': 'animationend' }, 17 animEndEventName = animEndEventNames[Modernizr.prefixed('animation')], 18 onEndAnimation = function (el, callback) { 19 var onEndCallbackFn = function (ev) { 20 if (support.animations) { 21 if (ev.target != this) return; 22 this.removeEventListener(animEndEventName, onEndCallbackFn); 23 } 24 if (callback && typeof callback === 'function') { callback.call(); } 25 }; 26 if (support.animations) { 27 el.addEventListener(animEndEventName, onEndCallbackFn); 28 } 29 else { 30 onEndCallbackFn(); 31 } 32 }; 33 34 function extend(a, b) { 35 for (var key in b) { 36 if (b.hasOwnProperty(key)) { 37 a[key] = b[key]; 38 } 39 } 40 return a; 41 } 42 43 function Stack(el, options) { 44 this.el = el; 45 this.options = extend({}, this.options); 46 extend(this.options, options); 47 this.items = [].slice.call(this.el.children); 48 this.itemsTotal = this.items.length; 49 if (this.options.infinite && this.options.visible >= this.itemsTotal || !this.options.infinite && this.options.visible > this.itemsTotal || this.options.visible <= 0) { 50 this.options.visible = 1; 51 } 52 this.current = 0; 53 this._init(); 54 } 55 56 Stack.prototype.options = { 57 // cardstack's perspective value 58 perspective: 1000, 59 // cardstack's perspective origin 60 perspectiveOrigin: '50% -50%', 61 // number of visible items in the cardstack 62 visible: 3, 63 // infinite navigation 64 infinite: true, 65 // callback: when reaching the end of the cardstack 66 onEndStack: function () { return false; }, 67 // animation settings for the items' movements in the cardstack when the items rearrange 68 // object that is passed to the dynamicsjs animate function (see more at http://dynamicsjs.com/) 69 // example: 70 // {type: dynamics.spring,duration: 1641,frequency: 557,friction: 459,anticipationSize: 206,anticipationStrength: 392} 71 cardstackItemsAnimation: { 72 duration: 500, 73 type: dynamics.bezier, 74 points: [{ 'x': 0, 'y': 0, 'cp': [{ 'x': 0.25, 'y': 0.1 }] }, { 'x': 1, 'y': 1, 'cp': [{ 'x': 0.25, 'y': 1 }] }] 75 }, 76 // delay for the items' rearrangement / delay before cardstackItemsAnimation is applied 77 cardstackItemsAnimationDelay: 0, 78 // animation settings for the items' movements in the cardstack before the rearrangement 79 // we can set up different settings depending on whether we are approving or rejecting an item 80 /* 81 cardstackItemsPreAnimation : { 82 reject : { 83 // if true, then the settings.properties parameter will be distributed through the items in a non equal fashion 84 // for instance, if we set settings.properties = {translateX:100} and we have options.visible = 4, 85 // then the second item in the cardstack will translate 100px, the second one 75px and the third 50px 86 elastic : true, 87 // object that is passed into the dynamicsjs animate function - second parameter - (see more at http://dynamicsjs.com/) 88 animationProperties : {}, 89 // object that is passed into the dynamicsjs animate function - third parameter - (see more at http://dynamicsjs.com/) 90 animationSettings : {} 91 }, 92 accept : { 93 // if true, then the settings.properties parameter will be distributed through the items in a non equal fashion 94 // for instance, if we set settings.properties = {translateX:100} and we have options.visible = 4, 95 // then the second item on the cardstack will translate 100px, the second one 75px and the third 50px 96 elastic : true, 97 // object that is passed into the dynamicsjs animate function - second parameter - (see more at http://dynamicsjs.com/) 98 animationProperties : {}, 99 // object that is passed into the dynamicsjs animate function (see more at http://dynamicsjs.com/) 100 animationSettings : {} 101 } 102 } 103 */ 104 }; 105 106 // set the initial styles for the visible items 107 Stack.prototype._init = function () { 108 // set default styles 109 // first, the cardstack 110 this.el.style.WebkitPerspective = this.el.style.perspective = this.options.perspective + 'px'; 111 this.el.style.WebkitPerspectiveOrigin = this.el.style.perspectiveOrigin = this.options.perspectiveOrigin; 112 113 var self = this; 114 115 // the items 116 for (var i = 0; i < this.itemsTotal; ++i) { 117 var item = this.items[i]; 118 if (i < this.options.visible) { 119 item.style.opacity = 1; 120 item.style.pointerEvents = 'auto'; 121 item.style.zIndex = i === 0 ? parseInt(this.options.visible + 1) : parseInt(this.options.visible - i); 122 item.style.WebkitTransform = item.style.transform = 'translate3d(0px, 0px, ' + parseInt(-1 * 50 * i) + 'px)'; 123 } 124 else { 125 item.style.WebkitTransform = item.style.transform = 'translate3d(0,
1250,-' + parseInt(this.options.visible * 50) + 'px)'; 126 } 127 } 128 129 classie.add(this.items[this.current], 'cardstack__item--current'); 130 }; 131 132 Stack.prototype.reject = function (callback) { 133 this._next('reject', callback); 134 }; 135 136 Stack.prototype.accept = function (callback) { 137 this._next('accept', callback); 138 }; 139 140 Stack.prototype.restart = function () { 141 this.hasEnded = false; 142 this._init(); 143 }; 144 145 Stack.prototype._next = function (action, callback) { 146 if (this.isAnimating || (!this.options.infinite && this.hasEnded)) return; 147 this.isAnimating = true; 148 149 // current item 150 var currentItem = this.items[this.current]; 151 classie.remove(currentItem, 'cardstack__item--current'); 152 153 // add animation class 154 classie.add(currentItem, action === 'accept' ? 'cardstack__item--accept' : 'cardstack__item--reject'); 155 156 var self = this; 157 onEndAnimation(currentItem, function () { 158 // reset current item 159 currentItem.style.opacity = 0; 160 currentItem.style.pointerEvents = 'none'; 161 currentItem.style.zIndex = -1; 162 currentItem.style.WebkitTransform = currentItem.style.transform = 'translate3d(0px, 0px, -' + parseInt(self.options.visible * 50) + 'px)'; 163 164 classie.remove(currentItem, action === 'accept' ? 'cardstack__item--accept' : 'cardstack__item--reject'); 165 166 self.items[self.current].style.zIndex = self.options.visible + 1; 167 self.isAnimating = false; 168 169 if (callback) callback(); 170 171 if (!self.options.infinite && self.current === 0) { 172 self.hasEnded = true; 173 // callback 174 self.options.onEndStack(self); 175 } 176 }); 177 178 // set style for the other items 179 for (var i = 0; i < this.itemsTotal; ++i) { 180 if (i >= this.options.visible) break; 181 182 if (!this.options.infinite) { 183 if (this.current + i >= this.itemsTotal - 1) break; 184 var pos = this.current + i + 1; 185 } 186 else { 187 var pos = this.current + i < this.itemsTotal - 1 ? this.current + i + 1 : i - (this.itemsTotal - this.current - 1); 188 } 189 190 var item = this.items[pos], 191 // cardstack items animation 192 animateStackItems = function (item, i) { 193 item.style.pointerEvents = 'auto'; 194 item.style.opacity = 1; 195 item.style.zIndex = parseInt(self.options.visible - i); 196 197 dynamics.animate(item, { 198 translateZ: parseInt(-1 * 50 * i) 199 }, self.options.cardstackItemsAnimation); 200 }; 201 202 setTimeout(function (item, i) { 203 return function () { 204 var preAnimation; 205 206 if (self.options.cardstackItemsPreAnimation) { 207 preAnimation = action === 'accept' ? self.options.cardstackItemsPreAnimation.accept : self.options.cardstackItemsPreAnimation.reject; 208 } 209 210 if (preAnimation) { 211 // items "pre animation" properties 212 var animProps = {}; 213 214 for (var key in preAnimation.animationProperties) { 215 var interval = preAnimation.elastic ? preAnimation.animationProperties[key] / self.options.visible : 0; 216 animProps[key] = preAnimation.animationProperties[key] - Number(i * interval); 217 } 218 219 // this one remains the same.. 220 animProps.translateZ = parseInt(-1 * 50 * (i + 1)); 221 222 preAnimation.animationSettings.complete = function () { 223 animateStackItems(item, i); 224 }; 225 226 dynamics.animate(item, animProps, preAnimation.animationSettings); 227 } 228 else { 229 animateStackItems(item, i); 230 } 231 }; 232 }(item, i), this.options.cardstackItemsAnimationDelay); 233 } 234 235 // update current 236 this.current = this.current < this.itemsTotal - 1 ? this.current + 1 : 0; 237 classie.add(this.items[this.current], 'cardstack__item--current'); 238 } 239 240 window.Stack = Stack; 241 242})(window);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.