1/* 2 3 * simplyScroll 2 - a scroll-tastic jQuery plugin 4 5 * 6 7 * http://logicbox.net/jquery/simplyscroll/ 8 9 * 10 11 * Copyright (c) 2009-2012 Will Kelly - http://logicbox.net 12 13 * 14 15 * Dual licensed under the MIT and GPL licenses. 16 17 * 18 19 * Version: 2.0.5 Last revised: 10/05/2012 20 21 * 22 23 */ 24 25 26 27(function($,window,undefined) { 28 29 30 31$.fn.simplyScroll = function(options) { 32 33 return this.each(function() { 34 35 new $.simplyScroll(this,options); 36 37 }); 38 39}; 40 41 42 43var defaults = { 44 45 customClass: 'simply-scroll', 46 47 frameRate: 24, //No of movements per second 48 49 speed: 1, //No of pixels per frame 50 51 orientation: 'horizontal', //'horizontal or 'vertical' - not to be confused with device orientation 52 53 auto: true, 54 55 autoMode: 'loop', //auto = true, 'loop' or 'bounce', 56 57 manualMode: 'end', //auto = false, 'loop' or 'end' 58 59 direction: 'forwards', //'forwards' or 'backwards'. 60 61 pauseOnHover: true, //autoMode = loop|bounce only 62 63 pauseOnTouch: true, //" touch device only 64 65 pauseButton: false, //" generates an extra element to allow manual pausing 66 67 startOnLoad: false //use this to delay starting of plugin until all page assets have loaded 68 69}; 70 71 72 73$.simplyScroll = function(el,options) { 74 75 76 77 var self = this; 78 79 80 81 this.o = $.extend({}, defaults, options || {}); 82 83 this.isAuto = this.o.auto!==false && this.o.autoMode.match(/^loop|bounce$/)!==null; 84 85 this.isHorizontal = this.o.orientation.match(/^horizontal|vertical$/)!==null && this.o.orientation==defaults.orientation; 86 87 this.isRTL = this.isHorizontal && $("html").attr('dir') == 'rtl'; 88 89 this.isForwards = !this.isAuto || (this.isAuto && this.o.direction.match(/^forwards|backwards$/)!==null && this.o.direction==defaults.direction) && !this.isRTL; 90 91 this.isLoop = this.isAuto && this.o.autoMode == 'loop' || !this.isAuto && this.o.manualMode == 'loop'; 92 93 94 95 this.supportsTouch = ('createTouch' in document); 96 97 98 99 this.events = this.supportsTouch ? 100 101 {start:'touchstart MozTouchDown',move:'touchmove MozTouchMove',end:'touchend touchcancel MozTouchRelease'} : 102 103 {start:'mouseenter',end:'mouseleave'}; 104 105 106 107 this.$list = $(el); //called on ul/ol/div etc 108 109 var $items = this.$list.children(); 110 111 112 113 //generate extra markup 114 115 this.$list.addClass('simply-scroll-list') 116 117 .wrap('<div class="simply-scroll-clip"></div>') 118 119 .parent().wrap('<div class="' + this.o.customClass + ' simply-scroll-container"></div>'); 120 121 122 123 if (!this.isAuto) { //button placeholders 124 125 this.$list.parent().parent() 126
127 .prepend('<div class="simply-scroll-forward"></div>') 128 129 .prepend('<div class="simply-scroll-back"></div>'); 130 131 } else { 132 133 if (this.o.pauseButton) { 134 135 this.$list.parent().parent() 136 137 .prepend('<div class="simply-scroll-btn simply-scroll-btn-pause"></div>'); 138 139 this.o.pauseOnHover = false; 140 141 } 142 143 } 144 145 146 147 //wrap an extra div around the whole lot if elements scrolled aren't equal 148 149 if ($items.length > 1) { 150 151 152 153 var extra_wrap = false, 154 155 total = 0; 156 157 158 159 if (this.isHorizontal) { 160 161 $items.each(function() { total+=$(this).outerWidth(true); }); 162 163 extra_wrap = $items.eq(0).outerWidth(true) * $items.length !== total; 164 165 } else { 166 167 $items.each(function() { total+=$(this).outerHeight(true); }); 168 169 extra_wrap = $items.eq(0).outerHeight(true) * $items.length !== total; 170 171 } 172 173 174 175 if (extra_wrap) { 176 177 this.$list = this.$list.wrap('<div></div>').parent().addClass('simply-scroll-list'); 178 179 if (this.isHorizontal) { 180 181 this.$list.children().css({"float":'left',width: total + 'px'}); 182 183 } else { 184 185 this.$list.children().css({height: total + 'px'}); 186 187 } 188 189 } 190 191 } 192 193 194 195 if (!this.o.startOnLoad) { 196 197 this.init(); 198 199 } else { 200 201 //wait for load before completing setup 202 203 $(window).load(function() { self.init(); }); 204 205 } 206 207 208 209}; 210 211 212 213$.simplyScroll.fn = $.simplyScroll.prototype = {}; 214 215 216 217$.simplyScroll.fn.extend = $.simplyScroll.extend = $.extend; 218 219 220 221$.simplyScroll.fn.extend({ 222 223 init: function() { 224 225 226 227 this.$items = this.$list.children(); 228 229 this.$clip = this.$list.parent(); //this is the element that scrolls 230 231 this.$container = this.$clip.parent(); 232 233 this.$btnBack = $('.simply-scroll-back',this.$container); 234 235 this.$btnForward = $('.simply-scroll-forward',this.$container); 236 237 238 239 if (!this.isHorizontal) { 240 241 this.itemMax = this.$items.eq(0).outerHeight(true); 242 243 this.clipMax = this.$clip.height(); 244 245 this.dimension = 'height'; 246 247 this.moveBackClass = 'simply-scroll-btn-up'; 248 249 this.moveForwardClass = 'simply-scroll-btn-down'; 250 251 this.scrollPos = 'Top'; 252 253 } else { 254 255 this.itemMax = this.$items.eq(0).outerWidth(true); 256 257 this.clipMax = this.$clip.width(); 258 259 this.dimension = 'width'; 260 261 this.moveBackClass = 'simply-scroll-btn-left'; 262 263 this.moveForwardClass = 'simply-scroll-btn-right'; 264 265 this.scrollPos = 'Left'; 266 267 } 268 269 270 271 this.posMin = 0; 272 273 274 275 this.posMax = this.$items.length * this.itemMax; 276 277 278 279 var addItems = Math.ceil(this.clipMax / this.itemMax); 280 281 282 283 //auto scroll loop & manual scroll bounce or end(to-end) 284 285 if (this.isAuto && this.o.autoMode=='loop') { 286 287 288 289 this.$list.css(this.dimension,this.posMax+(this.itemMax*addItems) +'px'); 290 291 292 293 this.posMax += (this.clipMax - this.o.speed); 294 295 296 297 if (this.isForwards) { 298 299 this.$items.slice(0,addItems).clone(true).appendTo(this.$list); 300 301 this.resetPosition = 0; 302 303 304 305 } else { 306 307 this.$items.slice(-addItems).clone(true).prependTo(this.$list); 308 309 this.resetPosition = this.$items.length * this.itemMax; 310 311 //due to inconsistent RTL implementation force back to LTR then fake 312 313 if (this.isRTL) { 314 315 this.$clip[0].dir = 'ltr'; 316 317 //based on feedback seems a good idea to force float right 318 319 this.$items.css('float','right'); 320 321 } 322 323 } 324 325 326 327 //manual and loop 328 329 } else if (!this.isAuto && this.o.manualMode=='loop') { 330 331 332 333 this.posMax += this.itemMax * addItems; 334 335 336 337 this.$list.css(this.dimension,this.posMax+(this.itemMax*addItems) +'px'); 338 339 340 341 this.posMax += (this.clipMax - this.o.speed); 342 343 344 345 var items_append = this.$items.slice(0,addItems).clone(true).appendTo(this.$list); 346 347 var items_prepend = this.$items.slice(-addItems).clone(true).prependTo(this.$list); 348 349 350 351 this.resetPositionForwards = this.resetPosition = addItems * this.itemMax; 352 353 this.resetPositionBackwards = this.$items.length * this.itemMax; 354 355 356 357 //extra events to force scroll direction change 358 359 var self = this; 360 361 362 363 this.$btnBack.bind(this.events.start,function() { 364 365 self.isForwards = false; 366 367 self.resetPosition = self.resetPositionBackwards; 368 369 }); 370 371 372 373 this.$btnForward.bind(this.events.start,function() { 374 375 self.isForwards = true; 376 377 self.resetPosition = self.resetPositionForwards; 378 379 }); 380 381 382 383 } else { //(!this.isAuto && this.o.manualMode=='end') 384 385 386 387 this.$list.css(this.dimension,this.posMax +'px'); 388 389 390 391 if (this.isForwards) { 392 393 this.resetPosition = 0; 394 395 396 397 } else { 398 399 this.resetPosition = this.$items.length * this.itemMax; 400 401 //due to inconsistent RTL implementation force back to LTR then fake 402 403 if (this.isRTL) { 404 405 this.$clip[0].dir = 'ltr'; 406 407 //based on feedback seems a good idea to force float right 408 409 this.$items.css('float','right'); 410 411 } 412 413 } 414 415 } 416 417 418 419 this.resetPos() //ensure scroll position is reset 420 421 422 423 this.interval = null; 424 425 this.intervalDelay = Math.floor(1000 / this.o.frameRate); 426 427 428 429 if (!(!this.isAuto && this.o.manualMode=='end')) { //loop mode 430 431 //ensure that speed is divisible by item width. Helps to always make images even not odd widths! 432 433 while (this.itemMax % this.o.speed !== 0) { 434 435 this.o.speed--; 436 437 if (this.o.speed===0) { 438 439 this.o.speed=1; break; 440 441 } 442 443 } 444 445 } 446 447 448 449 var self = this; 450 451 this.trigger = null; 452 453 this.funcMoveBack = function(e) { 454 455 if (e !== undefined) { 456 457 e.preventDefault(); 458 459 } 460 461 self.trigger = !self.isAuto && self.o.manualMode=='end' ? this : null; 462 463 if (self.isAuto) { 464 465 self.isForwards ? self.moveBack() : self.moveForward(); 466 467 } else { 468 469 self.moveBack(); 470 471 } 472 473 }; 474 475 this.funcMoveForward = function(e) { 476 477 if (e !== undefined) { 478 479 e.preventDefault(); 480 481 } 482 483 self.trigger = !self.isAuto && self.o.manualMode=='end' ? this : null; 484 485 if (self.isAuto) { 486 487 self.isForwards ? self.moveForward() : self.moveBack(); 488 489 } else { 490 491 self.moveForward(); 492 493 } 494 495 }; 496 497 this.funcMovePause = function() { self.movePause(); }; 498 499 this.funcMoveStop = function() { self.moveStop(); }; 500 501 this.funcMoveResume = function() { self.moveResume(); }; 502 503 504 505 506 507 508 509 if (this.isAuto) { 510 511 512 513 this.paused = false; 514 515 516 517 function togglePause() { 518 519 if (self.paused===false) { 520 521 self.paused=true; 522 523 self.funcMovePause(); 524 525 } else { 526 527 self.paused=false; 528 529 self.funcMoveResume(); 530 531 } 532 533 return self.paused; 534 535 }; 536 537 538 539 //disable pauseTouch when links are present 540 541 if (this.supportsTouch && this.$items.find('a').length) { 542 543 this.supportsTouch=false; 544 545 } 546 547 548 549 if (this.isAuto && this.o.pauseOnHover && !this.supportsTouch) { 550 551 this.$clip.bind(this.events.start,this.funcMovePause).bind(this.events.end,this.funcMoveResume); 552 553 } else if (this.isAuto && this.o.pauseOnTouch && !this.o.pauseButton && this.supportsTouch) { 554 555 556 557 var touchStartPos, scrollStartPos; 558 559 560 561 this.$clip.bind(this.events.start,function(e) { 562 563 togglePause(); 564 565 var touch = e.originalEvent.touches[0]; 566 567 touchStartPos = self.isHorizontal ? touch.pageX : touch.pageY; 568 569 scrollStartPos = self.$clip[0]['scroll' + self.scrollPos]; 570 571 e.stopPropagation(); 572 573 e.preventDefault(); 574 575 576 577 }).bind(this.events.move,function(e) { 578 579 580 581 e.stopPropagation(); 582 583 e.preventDefault(); 584 585 586 587 var touch = e.originalEvent.touches[0], 588 589 endTouchPos = self.isHorizontal ? touch.pageX : touch.pageY, 590 591 pos = (touchStartPos - endTouchPos) + scrollStartPos; 592 593 594 595 if (pos < 0) pos = 0; 596 597 else if (pos > self.posMax) pos = self.posMax; 598 599 600 601 self.$clip[0]['scroll' + self.scrollPos] = pos; 602 603 604 605 //force pause 606 607 self.funcMovePause(); 608 609 self.paused = true; 610 611 }); 612 613 } else { 614 615 if (this.o.pauseButton) { 616 617 618 619 this.$btnPause = $(".simply-scroll-btn-pause",this.$container) 620 621 .bind('click',function(e) { 622 623 e.preventDefault(); 624 625 togglePause() ? $(this).addClass('active') : $(this).removeClass('active'); 626 627 });
628 629 } 630 631 } 632 633 this.funcMoveForward(); 634 635 } else { 636 637 638 639 this.$btnBack 640 641 .addClass('simply-scroll-btn' + ' ' + this.moveBackClass) 642 643 .bind(this.events.start,this.funcMoveBack).bind(this.events.end,this.funcMoveStop); 644 645 this.$btnForward 646 647 .addClass('simply-scroll-btn' + ' ' + this.moveForwardClass) 648 649 .bind(this.events.start,this.funcMoveForward).bind(this.events.end,this.funcMoveStop); 650 651 652 653 if (this.o.manualMode == 'end') { 654 655 !this.isRTL ? this.$btnBack.addClass('disabled') : this.$btnForward.addClass('disabled'); 656 657 } 658 659 } 660 661 }, 662 663 moveForward: function() { 664 665 var self = this; 666 667 this.movement = 'forward'; 668 669 if (this.trigger !== null) { 670 671 this.$btnBack.removeClass('disabled'); 672 673 } 674 675 self.interval = setInterval(function() { 676 677 if (self.$clip[0]['scroll' + self.scrollPos] < (self.posMax-self.clipMax)) { 678 679 self.$clip[0]['scroll' + self.scrollPos] += self.o.speed; 680 681 } else if (self.isLoop) { 682 683 self.resetPos(); 684 685 } else { 686 687 self.moveStop(self.movement); 688 689 } 690 691 },self.intervalDelay); 692 693 }, 694 695 moveBack: function() { 696 697 var self = this; 698 699 this.movement = 'back'; 700 701 if (this.trigger !== null) { 702 703 this.$btnForward.removeClass('disabled'); 704 705 } 706 707 self.interval = setInterval(function() { 708 709 if (self.$clip[0]['scroll' + self.scrollPos] > self.posMin) { 710 711 self.$clip[0]['scroll' + self.scrollPos] -= self.o.speed; 712 713 } else if (self.isLoop) { 714 715 self.resetPos(); 716 717 } else { 718 719 self.moveStop(self.movement); 720 721 } 722 723 },self.intervalDelay); 724 725 }, 726 727 movePause: function() { 728 729 clearInterval(this.interval); 730 731 }, 732 733 moveStop: function(moveDir) { 734 735 this.movePause(); 736 737 if (this.trigger!==null) { 738 739 if (typeof moveDir !== 'undefined') { 740 741 $(this.trigger).addClass('disabled'); 742 743 } 744 745 this.trigger = null; 746 747 } 748 749 if (this.isAuto) { 750 751 if (this.o.autoMode=='bounce') { 752 753 moveDir == 'forward' ? this.moveBack() : this.moveForward(); 754 755 } 756 757 } 758 759 }, 760 761 moveResume: function() { 762 763 this.movement=='forward' ? this.moveForward() : this.moveBack(); 764 765 }, 766 767 resetPos: function() { 768 769 this.$clip[0]['scroll' + this.scrollPos] = this.resetPosition; 770 771 } 772 773}); 774 775 776 777})(jQuery,window); 778
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.