PageRenderTime 54ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/files/jquery.simplyscroll/2.0.5/jquery.simplyscroll.js

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