Lungo.Element.Carousel.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /**
  2. * Creates a instance of Carousel Element
  3. *
  4. * @namespace Lungo.Element
  5. * @class Carousel
  6. * @version 1.0
  7. *
  8. * @author Ignacio Olalde <ina@tapquo.com> || @piniphone
  9. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  10. */
  11. Lungo.Element.Carousel = function(element, callback) {
  12. var _instance = {
  13. index: 0,
  14. speed: 300,
  15. callback: callback,
  16. container: element,
  17. element: element.children[0],
  18. slide: undefined,
  19. slides: [],
  20. slides_length: 0,
  21. width: 0,
  22. start: {},
  23. isScrolling: undefined,
  24. deltaX: 0
  25. };
  26. var prev = function(delay) {
  27. if (_instance.index) {
  28. _slide(_instance.index-1, _instance.speed);
  29. }
  30. };
  31. var next = function(delay) {
  32. if (_instance.index < _instance.slides_length - 1) {
  33. _slide(_instance.index + 1, _instance.speed);
  34. } else {
  35. _slide(0, _instance.speed);
  36. }
  37. };
  38. var position = function() {
  39. return _instance.index;
  40. };
  41. var refresh = function() {
  42. _setup();
  43. };
  44. var _setup = function() {
  45. _instance.slides = _instance.element.children;
  46. _instance.slides_length = _instance.slides.length;
  47. if (_instance.slides_length < 2) return null;
  48. _instance.width = ("getBoundingClientRect" in _instance.container) ?
  49. _instance.container.getBoundingClientRect().width :
  50. _instance.container.offsetWidth;
  51. if (!_instance.width) return null;
  52. _instance.element.style.width = (_instance.slides.length * _instance.width) + 'px';
  53. var index = _instance.slides.length;
  54. while (index--) {
  55. var el = _instance.slides[index];
  56. el.style.width = _instance.width + 'px';
  57. el.style.display = 'table-cell';
  58. el.style.verticalAlign = 'top';
  59. }
  60. _slide(_instance.index, 0);
  61. _instance.container.style.visibility = 'visible';
  62. };
  63. var _slide = function(index, duration) {
  64. var style = _instance.element.style;
  65. if (duration == undefined) {
  66. duration = _instance.speed;
  67. }
  68. style.webkitTransitionDuration = style.MozTransitionDuration =
  69. style.msTransitionDuration = style.OTransitionDuration = style.transitionDuration =
  70. duration + 'ms';
  71. style.MozTransform = style.webkitTransform = 'translate3d(' + -(index * _instance.width) + 'px,0,0)';
  72. style.msTransform = style.OTransform = 'translateX(' + -(index * _instance.width) + 'px)';
  73. _instance.index = index;
  74. };
  75. var _handleGestures = function() {
  76. _instance.element.addEventListener('touchstart', _touchStart, false);
  77. _instance.element.addEventListener('touchmove', _touchMove, false);
  78. _instance.element.addEventListener('touchend', _touchEnd, false);
  79. _instance.element.addEventListener('webkitTransitionEnd', _transitionEnd, false);
  80. _instance.element.addEventListener('msTransitionEnd', _transitionEnd, false);
  81. _instance.element.addEventListener('oTransitionEnd', _transitionEnd, false);
  82. _instance.element.addEventListener('transitionend', _transitionEnd, false);
  83. window.addEventListener('resize', _setup, false);
  84. };
  85. var _touchStart = function(event) {
  86. _instance.start = {
  87. pageX: event.touches[0].pageX,
  88. pageY: event.touches[0].pageY,
  89. time: Number(new Date())
  90. };
  91. _instance.isScrolling = undefined;
  92. _instance.deltaX = 0;
  93. _instance.element.style.MozTransitionDuration = _instance.element.style.webkitTransitionDuration = 0;
  94. event.stopPropagation();
  95. };
  96. var _touchMove = function(e) {
  97. if(e.touches.length > 1 || e.scale && e.scale !== 1) return;
  98. _instance.deltaX = e.touches[0].pageX - _instance.start.pageX;
  99. if ( typeof _instance.isScrolling == 'undefined') {
  100. _instance.isScrolling = !!( _instance.isScrolling || Math.abs(_instance.deltaX) < Math.abs(e.touches[0].pageY - _instance.start.pageY) );
  101. }
  102. if (!_instance.isScrolling) {
  103. e.preventDefault();
  104. var factor = ((!_instance.index && _instance.deltaX > 0
  105. || _instance.index == _instance.slides_length - 1
  106. && _instance.deltaX < 0
  107. ) ?
  108. (Math.abs(_instance.deltaX) / _instance.width + 1)
  109. :1);
  110. _instance.deltaX = _instance.deltaX / factor;
  111. var pos = (_instance.deltaX - _instance.index * _instance.width);
  112. _instance.element.style.MozTransform = _instance.element.style.webkitTransform = 'translate3d(' + pos + 'px,0,0)';
  113. e.stopPropagation();
  114. }
  115. };
  116. var _touchEnd = function(e) {
  117. var isValidSlide =
  118. Number(new Date()) - _instance.start.time < 250
  119. && Math.abs(_instance.deltaX) > 20
  120. || Math.abs(_instance.deltaX) > _instance.width/2;
  121. var isPastBounds =
  122. !_instance.index && _instance.deltaX > 0
  123. || _instance.index == _instance.slides_length - 1
  124. && _instance.deltaX < 0;
  125. if (!_instance.isScrolling) {
  126. _slide( _instance.index + ( isValidSlide && !isPastBounds ? (_instance.deltaX < 0 ? 1 : -1) : 0 ), _instance.speed );
  127. }
  128. e.stopPropagation();
  129. };
  130. var _transitionEnd = function(event) {
  131. if(_instance.callback) {
  132. _instance.callback.apply(_instance.callback, [_instance.index, _instance.slides[_instance.index]]);
  133. }
  134. };
  135. _setup();
  136. _handleGestures();
  137. return {
  138. prev: prev,
  139. next: next,
  140. position: position,
  141. refresh: refresh
  142. };
  143. };