1;(function (factory) { 2 if(typeof module === "object" && typeof module.exports === "object") { 3 factory(require("jquery"), window, document); 4 } else { 5 factory(jQuery, window, document); 6 } 7}( function( $, window, document, undefined ) { 8 9 "use strict"; 10 11 var pluginName = "cardslider", 12 defaults = { 13 keys: { 14 next: 38, 15 prev: 40 16 }, 17 direction: 'down', 18 nav: true, 19 swipe: false, 20 dots: false, 21 loop: false, 22 beforeCardChange: null, 23 afterCardChange: null, 24 showCards: 0 25 }; 26 27 function Plugin ( element, options ) { 28 this.element = element; 29 30 options.showCards-=1; 31 32 this.settings = $.extend( {}, defaults, options ); 33 this._defaults = defaults; 34 this._name = pluginName; 35 this._cards = []; 36 this._activeCard = null; 37 this._directionClass = 'cardslider--direction-'+this.settings.direction; 38 this._animationClassBack = 'cardslider--sortback-'+this.settings.direction; 39 this._animationClassFront = 'cardslider--sortfront-'+this.settings.direction; 40 this._dotnav = null; 41 this._directionnav = null; 42 this._buttonNext = null; 43 this._buttonPrev = null; 44 this._xDown = null; 45 this._yDown = null; 46 this._swipeThreshold = 100; 47 48 this.init(); 49 } 50 51 $.extend( Plugin.prototype, { 52 init: function() { 53 54 this.initCards(); 55 56 if(this.settings.nav) { 57 this.initNav(); 58 } 59 60 if(this.settings.dots) { 61 this.initDots(); 62 } 63 64 if(this.settings.swipe) { 65 this.initSwipe(); 66 } 67 68 if(this.settings.keys !== false) { 69 window.addEventListener('keydown', this.keyNav.bind(this)); 70 } 71 72 this.changeCardTo(0); 73 }, 74 initCards: function() { 75 76 this.element.className = this.element.className + ' cardslider ' + this._directionClass; 77 78 var list = this.element.querySelector('ul'); 79 if(!list) return false; 80 81 list.classList.add('cardslider__cards'); 82 83 var rawcards = list.children; 84 for(var i = 0; i < rawcards.length; i++) { 85 var rawcard = rawcards[i]; 86 87 var hidden = this.settings.showCards != 0 && i > this.settings.showCards; 88 89 var card = { 90 elem: rawcard, 91 active: i === 0? true : false, 92 index: i, 93 cardClass: 'cardslider__card--index-' + i 94 }; 95 96 card.elem.className = card.elem.className 97 + ' cardslider__card cardslider__card--transitions ' 98 + card.cardClass 99 + (hidden && ' cardslider__card--invisible'); 100 101 card.elem.style.zIndex = rawcards.length - i; 102 103 this._cards.push(card); 104 } 105 }, 106 initNav: function() { 107 this._directionnav = document.createElement('div'); 108 this._directionnav.className = 'cardslider__direction-nav'; 109 110 this._buttonNext = document.createElement('button'); 111 this._buttonNext.title = 'next'; 112 this._buttonNext.className = 'cardslider__nav-next'; 113 this._buttonNext.innerHTML = 'Next'; 114 this._buttonNext.addEventListener('click', this.nextCard.bind(this)); 115 116 this._buttonPrev = document.createElement('button'); 117 this._buttonPrev.title = 'previous'; 118 this._buttonPrev.className = 'cardslider__nav-prev'; 119 this._buttonPrev.innerHTML = 'Prev'; 120 this._buttonPrev.addEventListener('click', this.prevCard.bind(this)); 121 122 this._directionnav.appendChild(this._buttonNext); 123 this._directionnav.appendChild(this._buttonPrev); 124 this.element.appendChild(this._directionnav); 125 }, 126 initDots: function() { 127 var cardslider = this; 128 this._dotnav = document.createElement('ul'); 129 this._dotnav.className = 'cardslider__dots-nav'; 130 131 for(var i = 0; i < this._cards.length; i++) { 132 var dot = document.createElement('button'); 133 dot.className = 'cardslider__dot-btn'; 134 dot.setAttribute('data-slide', i); 135 dot.setAttribute('type', 'button'); 136 137 dot.addEventListener('click', function(e) { 138 cardslider.changeCardTo(parseInt(e.target.getAttribute('data-slide'))); 139 }); 140 141 var listItem = document.createElement('li'); 142 listItem.className = 'cardslider__dot'; 143 listItem.appendChild(dot) 144 this._dotnav.appendChild(listItem); 145 } 146 147 this.element.appendChild(this._dotnav); 148 }, 149 initSwipe: function() { 150 this.element.addEventListener('touchstart', this.handleTouchStart.bind(this), {passive:true}); 151 this.element.addEventListener('touchmove', this.handleTouchEnd.bind(this), {passive:true}); 152 }, 153 handleTouchStart: function(e) { 154 this._xDown = e.touches[0].clientX; 155 this._yDown = e.touches[0].clientY; 156 }, 157 handleTouchEnd: function(e) { 158 e.preventDefault(); 159 160 if ( ! this._xDown || ! this._yDown ) { 161 return; 162 } 163 164 var next = false;
165 var prev = false; 166 167 var xUp = e.touches[0].clientX; 168 var yUp = e.touches[0].clientY; 169 170 var xDiff = this._xDown - xUp; 171 var yDiff = this._yDown - yUp; 172 173 if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) { 174 175 if(Math.abs(xDiff) < this._swipeThreshold) {return;} 176 177 if ( xDiff > 0 ) { // left swipe 178 if(this.settings.direction == 'left') { 179 next = true; 180 } 181 else if(this.settings.direction == 'right') { 182 prev = true; 183 } 184 } else { //right swipe 185 if(this.settings.direction == 'right') { 186 next = true; 187 } 188 else if(this.settings.direction == 'left') { 189 prev = true; 190 } 191 } 192 } else { 193 194 if(Math.abs(yDiff) < this._swipeThreshold) {return;} 195 196 if ( yDiff > 0 ) { //up swipe 197 if(this.settings.direction == 'up') { 198 next = true; 199 } 200 else if(this.settings.direction == 'down') { 201 prev = true; 202 } 203 } else { //down swipe 204 if(this.settings.direction == 'down') { 205 next = true; 206 } 207 else if(this.settings.direction == 'up') { 208 prev = true; 209 } 210 } 211 } 212 213 if(next) { 214 this.nextCard(); 215 } 216 else if(prev) { 217 this.prevCard(); 218 } 219 220 this._xDown = null; 221 this._yDown = null; 222 }, 223 keyNav: function(e) { 224 if(e.keyCode == this.settings.keys.next) { 225 e.preventDefault(); 226 this.nextCard(); 227 } 228 else if(e.keyCode == this.settings.keys.prev) { 229 e.preventDefault(); 230 this.prevCard(); 231 } 232 }, 233 nextCard: function() { 234 if(this._activeCard.index + 1 < this._cards.length) { 235 this.changeCardTo(this._activeCard.index + 1); 236 } 237 else if(this.settings.loop) { 238 this.changeCardTo(0, true); 239 } 240 }, 241 prevCard: function() { 242 if(this._activeCard.index - 1 >= 0) { 243 this.changeCardTo(this._activeCard.index - 1); 244 } 245 else if(this.settings.loop) { 246 this.changeCardTo((this._cards.length-1)*-1); 247 } 248 }, 249 changeCardTo: function(index, resetZ) { 250 251 // set param default 252 resetZ = typeof resetZ != 'undefined'? resetZ : false; 253 254 // normalize indeX 255 if(typeof index == 'string') { 256 if(index == 'first') { 257 index = 0; 258 } 259 else { 260 index = this._cards.length-1; 261 } 262 } 263 264 var indexAbs = Math.abs(index); 265 266 // set variables for easy access 267 var oldCard = this._activeCard; 268 var newCard = this._cards[indexAbs]; 269 270 // remove left over animation classes 271 if(this.settings.loop) { 272 var that = this; 273 this._cards.forEach(function(card) { 274 card.elem.classList.remove(that._animationClassFront); 275 card.elem.classList.remove(that._animationClassBack); 276 card.elem.classList.add('cardslider__card--transitions'); 277 }); 278 } 279 280 // fire before callback 281 if(typeof this.settings.beforeCardChange == 'function') { 282 this.settings.beforeCardChange(oldCard.index); 283 } 284 285 if(oldCard && (index > oldCard.index || (index < oldCard.index && resetZ)) || !oldCard && index > 0) { 286 for(var i = 0; i < indexAbs; i++) { 287 288 this._cards[i].elem.setAttribute('aria-hidden', true); 289 290 if(!this.settings.loop) { 291 this._cards[i].elem.classList.add('cardslider__card--out'); 292 } 293 } 294 295 if(this.settings.loop && oldCard != null) { 296 oldCard.elem.classList.remove('cardslider__card--transitions'); 297 oldCard.elem.classList.add(this._animationClassBack); 298 } 299 } 300 else if(oldCard) { 301 if(this.settings.loop && oldCard) { 302 this._cards[indexAbs].elem.classList.remove('cardslider__card--transitions'); 303 this._cards[indexAbs].elem.classList.add(this._animationClassFront); 304 } 305 this._cards.forEach(function(card) { 306 card.elem.classList.add('cardslider__card--out'); 307 card.elem.setAttribute('aria-hidden', true); 308 }); 309 } 310 311 // make the front most card to the active one 312 this._activeCard = newCard; 313 this._activeCard.elem.setAttribute('aria-hidden', false); 314 315 // reorder all index classes to push the cards to their new position 316 this.reorderIndices(indexAbs); 317 318 // change the dot nav 319 if(this.settings.dots) { 320 this.changeDots(indexAbs); 321 } 322 323 // fire after callback 324 if(typeof this.settings.afterCardChange == 'function') { 325 this.settings.afterCardChange(indexAbs); 326 } 327 328 return this; 329 }, 330 changeDots: function(index) { 331 var active = this._dotnav.querySelector('.cardslider__dot--active'); 332 if(active) { 333 active.classList.remove('cardslider__dot--active'); 334 } 335 336 var next = this._dotnav.querySelector('.cardslider__dot:nth-child('+(index+1)+')'); 337 if(next) { 338 next.classList.add('cardslider__dot--active'); 339 } 340 }, 341 reorderIndices: function(index) { 342 var that = this; 343 var cardLen = that._cards.length - 1; 344 this._cards.forEach(function(card, i) { 345 if(i-index >= 0) { 346 var cardClasses = card.elem.className; 347 cardClasses = cardClasses.replace(/cardslider__card--index-\d|cardslider__card--out/g, ''); 348 card.elem.className = cardClasses.replace(' ',' ').trim(); 349
350 var newCardClass = that._cards[i-index].cardClass; 351 352 card.elem.classList.add(newCardClass); 353 354 var parsed = parseInt(newCardClass.slice(-1)); 355 356 if(parsed > that.settings.showCards) { 357 card.elem.classList.add('cardslider__card--invisible'); 358 } 359 else { 360 card.elem.classList.remove('cardslider__card--invisible'); 361 } 362 363 if(that.settings.loop) { 364 that.setZindex(card, cardLen - that._cards[i-index].index); 365 } 366 } 367 else if(that.settings.loop) { 368 var cardClasses = card.elem.className; 369 cardClasses = cardClasses.replace(/cardslider__card--index-\d|cardslider__card--out/g, ''); 370 card.elem.className = cardClasses.replace(' ',' ').trim(); 371 var newCardClass = that._cards[that._cards.length-(index-i)].cardClass; 372 card.elem.classList.add(newCardClass); 373 374 var parsed = parseInt(newCardClass.slice(-1)); 375 376 if(parsed > that.settings.showCards) { 377 card.elem.classList.add('cardslider__card--invisible'); 378 } 379 else { 380 card.elem.classList.remove('cardslider__card--invisible'); 381 } 382 383 that.setZindex(card, cardLen - that._cards[that._cards.length-(index-i)].index); 384 } 385 }); 386 }, 387 setZindex: function(elem, index) { 388 elem.elem.style.zIndex = index; 389 }, 390 destroy: function() { 391 var list = this.element.querySelector('.cardslider__cards'); 392 this.element.className = this.element.className.replace(this.element.className.match(/card.*/g)[0], ''); 393 394 list.classList.remove('cardslider__cards'); 395 396 this._cards.forEach(function(card) { 397 card.elem.className = card.elem.className.replace(card.elem.className.match(/card.*/g)[0], ''); 398 card.elem.removeAttribute('style'); 399 card.elem.removeAttribute('aria-hidden'); 400 }); 401 402 if(this._dotnav) { 403 this._dotnav.parentElement.removeChild(this._dotnav); 404 this._dotnav = null; 405 } 406 407 if(this._directionnav) { 408 this._directionnav.parentElement.removeChild(this._directionnav); 409 this._directionnav = null; 410 } 411 412 this._cards = []; 413 this._activeCard = null; 414 415 if(this.settings.keys !== false) { 416 window.removeEventListener('keydown', this.keyNav); 417 } 418 419 if(this._buttonNext) { 420 this._buttonNext.removeEventListener('cardslider', this.nextCard); 421 } 422 423 if(this._buttonPrev) { 424 this._buttonPrev.removeEventListener('cardslider', this.prevCard); 425 } 426 427 return this; 428 } 429 } ); 430 431 $.fn[ pluginName ] = function( options ) { 432 return this.each( function() { 433 if ( !$.data( this, pluginName ) ) { 434 $.data( this, pluginName, new Plugin( this, options ) ); 435 } 436 } ); 437 }; 438}));
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.