1/* 2 * simplyScroll 2 - a scroll-tastic jQuery plugin 3 * 4 * http://logicbox.net/jquery/simplyscroll/ 5 * 6 * Copyright (c) 2009-2012 Will Kelly - http://logicbox.net 7 * 8 * Dual licensed under the MIT and GPL licenses. 9 * 10 * Version: 2.0.5 Last revised: 10/05/2012 11 * 12 */ 13 14(function($,window,undefined) { 15 16 $.fn.simplyScroll = function(options) { 17 return this.each(function() { 18 new $.simplyScroll(this,options); 19 }); 20 }; 21 22 var defaults = { 23 customClass: 'simply-scroll', 24 frameRate: 24, //No of movements per second 25 speed: 1, //No of pixels per frame 26 orientation: 'horizontal', //'horizontal or 'vertical' - not to be confused with device orientation 27 auto: true, 28 autoMode: 'loop', //auto = true, 'loop' or 'bounce', 29 manualMode: 'end', //auto = false, 'loop' or 'end' 30 direction: 'forwards', //'forwards' or 'backwards'. 31 pauseOnHover: true, //autoMode = loop|bounce only 32 pauseOnTouch: true, //" touch device only 33 pauseButton: false, //" generates an extra element to allow manual pausing 34 startOnLoad: false //use this to delay starting of plugin until all page assets have loaded 35 }; 36 37 $.simplyScroll = function(el,options) { 38 39 var self = this; 40 41 this.o = $.extend({}, defaults, options || {}); 42 this.isAuto = this.o.auto!==false && this.o.autoMode.match(/^loop|bounce$/)!==null; 43 this.isHorizontal = this.o.orientation.match(/^horizontal|vertical$/)!==null && this.o.orientation==defaults.orientation; 44 this.isRTL = this.isHorizontal && $("html").attr('dir') == 'rtl'; 45 this.isForwards = !this.isAuto || (this.isAuto && this.o.direction.match(/^forwards|backwards$/)!==null && this.o.direction==defaults.direction) && !this.isRTL; 46 this.isLoop = this.isAuto && this.o.autoMode == 'loop' || !this.isAuto && this.o.manualMode == 'loop'; 47 48 this.supportsTouch = ('createTouch' in document); 49 50 this.events = this.supportsTouch ? 51 {start:'touchstart MozTouchDown',move:'touchmove MozTouchMove',end:'touchend touchcancel MozTouchRelease'} : 52 {start:'mouseenter',end:'mouseleave'}; 53 54 this.$list = $(el); //called on ul/ol/div etc 55 var $items = this.$list.children(); 56 57 //generate extra markup 58 this.$list.addClass('simply-scroll-list') 59 .wrap('<div class="simply-scroll-clip"></div>') 60 .parent().wrap('<div class="' + this.o.customClass + ' simply-scroll-container"></div>'); 61 62 if (!this.isAuto) { //button placeholders 63 this.$list.parent().parent() 64 .prepend('<div class="simply-scroll-forward"></div>') 65 .prepend('<div class="simply-scroll-back"></div>'); 66 } else { 67 if (this.o.pauseButton) { 68 this.$list.parent().parent() 69 .prepend('<div class="simply-scroll-btn simply-scroll-btn-pause"></div>'); 70 this.o.pauseOnHover = false; 71 } 72 } 73 74 //wrap an extra div around the whole lot if elements scrolled aren't equal 75 if ($items.length > 1) { 76 77 var extra_wrap = false, 78 total = 0; 79 80 if (this.isHorizontal) { 81 $items.each(function() { total+=$(this).outerWidth(true); }); 82 extra_wrap = $items.eq(0).outerWidth(true) * $items.length !== total; 83 } else { 84 $items.each(function() { total+=$(this).outerHeight(true); }); 85 extra_wrap = $items.eq(0).outerHeight(true) * $items.length !== total; 86 } 87 88 if (extra_wrap) { 89 this.$list = this.$list.wrap('<div></div>').parent().addClass('simply-scroll-list'); 90 if (this.isHorizontal) { 91 this.$list.children().css({"float":'left',width: total + 'px'}); 92 } else { 93 this.$list.children().css({height: total + 'px'}); 94 } 95 } 96 } 97 98 if (!this.o.startOnLoad) { 99 this.init(); 100 } else { 101 //wait for load before completing setup 102 $(window).load(function() { self.init(); }); 103 } 104 105 }; 106 107 $.simplyScroll.fn = $.simplyScroll.prototype = {}; 108 109 $.simplyScroll.fn.extend = $.simplyScroll.extend = $.extend; 110 111 $.simplyScroll.fn.extend({ 112 init: function() { 113 114 this.$items = this.$list.children(); 115 this.$clip = this.$list.parent(); //this is the element that scrolls 116 this.$container = this.$clip.parent(); 117 this.$btnBack = $('.simply-scroll-back',this.$container); 118 this.$btnForward = $('.simply-scroll-forward',this.$container); 119 120 if (!this.isHorizontal) { 121 this.itemMax = this.$items.eq(0).outerHeight(true); 122 this.clipMax = this.$clip.height(); 123 this.dimension = 'height'; 124 this.moveBackClass = 'simply-scroll-btn-up'; 125 this.moveForwardClass = 'simply-scroll-btn-down'; 126 this.scrollPos = 'Top'; 127 } else { 128 this.itemMax = this.$items.eq(0).outerWidth(true); 129 this.clipMax = this.$clip.width(); 130 this.dimension = 'width'; 131 this.moveBackClass = 'simply-scroll-btn-left'; 132 this.moveForwardClass = 'simply-scroll-btn-right'; 133 this.scrollPos = 'Left'; 134 } 135 136 this.posMin = 0; 137 138 this.posMax = this.$items.length * this.itemMax; 139 140 var addItems = Math.ceil(this.clipMax / this.itemMax); 141 142 //auto scroll loop & manual scroll bounce or end(to-end) 143 if (this.isAuto && this.o.autoMode=='loop') { 144 145 this.$list.css(this.dimension,this.posMax+(this.itemMax*addItems) +'px'); 146 147 this.posMax += (this.clipMax - this.o.speed); 148 149 if (this.isForwards) { 150 this.$items.slice(0,addItems).clone(true).appendTo(this.$list); 151 this.resetPosition = 0; 152 153 } else { 154 this.$items.slice(-addItems).clone(true).prependTo(this.$list); 155 this.resetPosition = this.$items.length * this.itemMax; 156 //due to inconsistent RTL implementation force back to LTR then fake 157 if (this.isRTL) { 158 this.$clip[0].dir = 'ltr'; 159 //based on feedback seems a good idea to force float right 160 this.$items.css('float','right'); 161 } 162 } 163 164 //manual and loop 165 } else if (!this.isAuto && this.o.manualMode=='loop') { 166 167 this.posMax += this.itemMax * addItems; 168 169 this.$list.css(this.dimension,this.posMax+(this.itemMax*addItems) +'px'); 170 171 this.posMax += (this.clipMax - this.o.speed); 172 173 var items_append = this.$items.slice(0,addItems).clone(true).appendTo(this.$list); 174 var items_prepend = this.$items.slice(-addItems).clone(true).prependTo(this.$list); 175 176 this.resetPositionForwards = this.resetPosition = addItems * this.itemMax; 177 this.resetPositionBackwards = this.$items.length * this.itemMax; 178 179 //extra events to force scroll direction change 180 var self = this; 181 182 this.$btnBack.bind(this.events.start,function() { 183 self.isForwards = false; 184 self.resetPosition = self.resetPositionBackwards; 185 }); 186 187 this.$btnForward.bind(this.events.start,function() { 188 self.isForwards = true; 189 self.resetPosition = self.resetPositionForwards; 190 }); 191 192 } else { //(!this.isAuto && this.o.manualMode=='end') 193 194 this.$list.css(this.dimension,this.posMax +'px'); 195 196 if (this.isForwards) { 197 this.resetPosition = 0; 198 199 } else { 200 this.resetPosition = this.$items.length * this.itemMax; 201 //due to inconsistent RTL implementation force back to LTR then fake 202 if (this.isRTL) { 203 this.$clip[0].dir = 'ltr'; 204 //based on feedback seems a good idea to force float right 205 this.$items.css('float','right'); 206 } 207 } 208 } 209 210 this.resetPos() //ensure scroll position is reset 211 212 this.interval = null; 213 this.intervalDelay = Math.floor(1000 / this.o.frameRate); 214 215 if (!(!this.isAuto && this.o.manualMode=='end')) { //loop mode 216 //ensure that speed is divisible by item width. Helps to always make images even not odd widths! 217 while (this.itemMax % this.o.speed !== 0) { 218 this.o.speed--; 219 if (this.o.speed===0) { 220 this.o.speed=1; break; 221 } 222 } 223 } 224 225 var self = this; 226 this.trigger = null; 227 this.funcMoveBack = function(e) { 228 if (e !== undefined) { 229 e.preventDefault(); 230 } 231 self.trigger = !self.isAuto && self.o.manualMode=='end' ? this : null; 232 if (self.isAuto) { 233 self.isForwards ? self.moveBack() : self.moveForward(); 234 } else { 235 self.moveBack(); 236 } 237 }; 238 this.funcMoveForward = function(e) { 239 if (e !== undefined) { 240 e.preventDefault(); 241 } 242 self.trigger = !self.isAuto && self.o.manualMode=='end' ? this : null; 243 if (self.isAuto) { 244 self.isForwards ? self.moveForward() : self.moveBack(); 245 } else { 246 self.moveForward(); 247 } 248 }; 249 this.funcMovePause = function() { self.movePause(); }; 250 this.funcMoveStop = function() { self.moveStop(); }; 251 this.funcMoveResume = function() { self.moveResume(); }; 252 253 254 255 if (this.isAuto) { 256 257 this.paused = false; 258 259 function togglePause() { 260 if (self.paused===false) { 261 self.paused=true; 262 self.funcMovePause(); 263 } else { 264 self.paused=false; 265 self.funcMoveResume(); 266 } 267 return self.paused; 268 }; 269 270 //disable pauseTouch when links are present 271 if (this.supportsTouch && this.$items.find('a').length) { 272 this.supportsTouch=false; 273 } 274 275 if (this.isAuto && this.o.pauseOnHover && !this.supportsTouch) { 276 this.$clip.bind(this.events.start,this.funcMovePause).bind(this.events.end,this.funcMoveResume); 277 } else if (this.isAuto && this.o.pauseOnTouch && !this.o.pauseButton && this.supportsTouch) { 278 279 var touchStartPos, scrollStartPos; 280 281 this.$clip.bind(this.events.start,function(e) { 282 togglePause(); 283 var touch = e.originalEvent.touches[0]; 284 touchStartPos = self.isHorizontal ? touch.pageX : touch.pageY; 285 scrollStartPos = self.$clip[0]['scroll' + self.scrollPos]; 286 e.stopPropagation(); 287 e.preventDefault(); 288 289 }).bind(this.events.move,function(e) { 290 291 e.stopPropagation(); 292 e.preventDefault(); 293 294 var touch = e.originalEvent.touches[0], 295 endTouchPos = self.isHorizontal ? touch.pageX : touch.pageY, 296 pos = (touchStartPos - endTouchPos) + scrollStartPos; 297 298 if (pos < 0) pos = 0; 299 else if (pos > self.posMax) pos = self.posMax; 300 301 self.$clip[0]['scroll' + self.scrollPos] = pos; 302 303 //force pause 304 self.funcMovePause(); 305 self.paused = true; 306 });
307 } else { 308 if (this.o.pauseButton) { 309 310 this.$btnPause = $(".simply-scroll-btn-pause",this.$container) 311 .bind('click',function(e) { 312 e.preventDefault(); 313 togglePause() ? $(this).addClass('active') : $(this).removeClass('active'); 314 }); 315 } 316 } 317 this.funcMoveForward(); 318 } else { 319 320 this.$btnBack 321 .addClass('simply-scroll-btn' + ' ' + this.moveBackClass) 322 .bind(this.events.start,this.funcMoveBack).bind(this.events.end,this.funcMoveStop); 323 this.$btnForward 324 .addClass('simply-scroll-btn' + ' ' + this.moveForwardClass) 325 .bind(this.events.start,this.funcMoveForward).bind(this.events.end,this.funcMoveStop); 326 327 if (this.o.manualMode == 'end') { 328 !this.isRTL ? this.$btnBack.addClass('disabled') : this.$btnForward.addClass('disabled'); 329 } 330 } 331 }, 332 moveForward: function() { 333 var self = this; 334 this.movement = 'forward'; 335 if (this.trigger !== null) { 336 this.$btnBack.removeClass('disabled'); 337 } 338 self.interval = setInterval(function() { 339 if (self.$clip[0]['scroll' + self.scrollPos] < (self.posMax-self.clipMax)) { 340 self.$clip[0]['scroll' + self.scrollPos] += self.o.speed; 341 } else if (self.isLoop) { 342 self.resetPos(); 343 } else { 344 self.moveStop(self.movement); 345 } 346 },self.intervalDelay); 347 }, 348 moveBack: function() { 349 var self = this; 350 this.movement = 'back'; 351 if (this.trigger !== null) { 352 this.$btnForward.removeClass('disabled'); 353 } 354 self.interval = setInterval(function() { 355 if (self.$clip[0]['scroll' + self.scrollPos] > self.posMin) { 356 self.$clip[0]['scroll' + self.scrollPos] -= self.o.speed; 357 } else if (self.isLoop) { 358 self.resetPos(); 359 } else { 360 self.moveStop(self.movement); 361 } 362 },self.intervalDelay); 363 }, 364 movePause: function() { 365 clearInterval(this.interval); 366 }, 367 moveStop: function(moveDir) { 368 this.movePause(); 369 if (this.trigger!==null) { 370 if (typeof moveDir !== 'undefined') { 371 $(this.trigger).addClass('disabled'); 372 } 373 this.trigger = null; 374 } 375 if (this.isAuto) { 376 if (this.o.autoMode=='bounce') { 377 moveDir == 'forward' ? this.moveBack() : this.moveForward(); 378 } 379 } 380 }, 381 moveResume: function() { 382 this.movement=='forward' ? this.moveForward() : this.moveBack(); 383 }, 384 resetPos: function() { 385 this.$clip[0]['scroll' + this.scrollPos] = this.resetPosition; 386 } 387 }); 388 389})(jQuery,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.