ddfullscreenslider.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /* DD Full Screen Slider
  2. * Created: May 20th, 2015 by DynamicDrive.com
  3. * Visit http://www.dynamicdrive.com/ for full source code
  4. */
  5. var ddfullscreenslider = (function($){
  6. document.createElement('section')
  7. document.createElement('article')
  8. var defaults = {
  9. addHash: true,
  10. sliderstate: 'open', // reserved for future use
  11. keycodeNavigation: [40, 38], // keyCode codes for down and up naivagion, respectively
  12. transitionDuration: '0.5s',
  13. swipeconfig: {peekamount: 100, mousedrag: true},
  14. onslide: function($slide, index){}
  15. }
  16. var transformprop = '' // variable to contain browser supported version of "transform" property
  17. function supportstranslate3d(){ // based on http://stackoverflow.com/a/12621264/4360074
  18. if (!window.getComputedStyle) {
  19. return false;
  20. }
  21. var $el = $('<div style="position:absolute" />').appendTo(document.body)
  22. var has3d
  23. $el.css('transform', 'translate3d(1px,1px,1px)')
  24. has3d = $el.css('transform')
  25. var findtransformprop = $el.get(0).style.cssText.match(/(\w|\-)*transform/i) // get "-vendor-transform" portion of CSS Text
  26. transformprop = (findtransformprop)? findtransformprop[0] : 'transform'
  27. $el.remove()
  28. return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
  29. }
  30. var $window = $(window)
  31. var $root = $('html')
  32. function ddfullscreenslider(setting){
  33. var translatesupport = supportstranslate3d()
  34. var s = $.extend({}, defaults, setting)
  35. var $slider = $('#' + s.sliderid)
  36. var $wrapper = $slider.find('div.slidewrapper').css({transitionDuration: s.transitionDuration})
  37. var $slides = $()
  38. var slideslength = 0
  39. var $nav = $()
  40. var thisslider = this
  41. var selectedindx = 0
  42. var hasharray = []
  43. var mouseslidetimer
  44. var swipeevts = {start:"", move:"", end:""}, swipestart = false, dy = 0, bounds = [,], scrollableclass = 'scrollable', bypassdrag = false
  45. var initialrun= true // indicate whether this is first time slider has run. After page loads, variable becomes false
  46. if (!translatesupport){
  47. s.transitionDuration = parseFloat(s.transitionDuration) * 1000
  48. }
  49. /** Function to call always after a slide is shown */
  50. function onslidealways($slide, index){
  51. if (!initialrun && s.addHash){
  52. var newhash = $nav.find('li').eq(selectedindx).find('a:eq(0)').attr('href')
  53. if (history.replaceState){
  54. history.replaceState(null, null, newhash)
  55. }
  56. else{
  57. window.location.hash = newhash
  58. }
  59. }
  60. s.onslide($slide, index) // user defined event handler
  61. }
  62. function hashtoselectedslide(hash){
  63. for (var i=0; i<hasharray.length; i++){
  64. if (hasharray[i][0] == hash){
  65. return i
  66. break
  67. }
  68. }
  69. return 0
  70. }
  71. function applybounds(val, swipedir){
  72. if (swipedir == "down"){
  73. return (translatesupport)? Math.max(-parseInt(bounds[1]), val) : Math.max(-bounds[1], val)
  74. }
  75. else{
  76. return (translatesupport)? Math.min(bounds[0], val) : Math.min(bounds[0], val)
  77. }
  78. }
  79. function isscrollable($target){ // check element finger is on is contained inside a "scrollable" element that's actually scrollable (scrollHeight exceeds container height)
  80. var $scrollel = $target.closest('.' + scrollableclass)
  81. var scrollel
  82. if ($scrollel.length == 1){
  83. scrollel = $scrollel.get(0)
  84. if (scrollel.offsetHeight < scrollel.scrollHeight){
  85. return true
  86. }
  87. }
  88. return false
  89. }
  90. /** Mousewheel and keyboard scroll related code. Requires jquery.mousewheel.min.js **/
  91. function mouseslide(deltaY){
  92. var targetindx = selectedindx
  93. if (deltaY < 0) // mouse down
  94. var targetindx = Math.min(slideslength-1, selectedindx+1)
  95. else if (deltaY > 0)
  96. var targetindx = Math.max(0, selectedindx-1)
  97. if (targetindx != selectedindx)
  98. thisslider.slideTo(targetindx)
  99. }
  100. $slider.on('mousewheel', function(event){
  101. clearTimeout(mouseslidetimer)
  102. var deltaY = event.deltaY
  103. mouseslidetimer = setTimeout(function(){
  104. mouseslide(deltaY)
  105. }, 100)
  106. return false
  107. })
  108. $(document).on('keyup', function(e){
  109. var targetindx = selectedindx
  110. if (e.keyCode == s.keycodeNavigation[0]) // key to go to next slide
  111. var targetindx = Math.min(slideslength-1, selectedindx+1)
  112. else if (e.keyCode == s.keycodeNavigation[1]) // key to go to previous slide
  113. var targetindx = Math.max(0, selectedindx-1)
  114. if (targetindx != selectedindx)
  115. thisslider.slideTo(targetindx)
  116. })
  117. /** Swipe/ Mouse Drag scroll related code **/
  118. swipeevts.start = 'touchstart' + (s.swipeconfig.mousedrag? ' mousedown' : '')
  119. swipeevts.move = 'touchmove.dragmove' + s.sliderid + (s.swipeconfig.mousedrag? ' mousemove.dragmove' + s.sliderid : '')
  120. swipeevts.end = 'touchend' + (s.swipeconfig.mousedrag? ' mouseup' : '')
  121. if (s.swipeconfig.mousedrag){
  122. $wrapper.bind('click', function(e){
  123. if ($wrapper.data('dy') != 0) // if dragging on belt instead of clicking on it
  124. e.preventDefault() // prevent default action
  125. })
  126. }
  127. $wrapper.bind(swipeevts.start, function(e){
  128. bypassdrag = false
  129. var e = (e.type.indexOf('touch') != -1)? e.originalEvent.changedTouches[0] : e
  130. if ( isscrollable( $(e.target) ) ){ // if target is contained inside a "scrollable" element
  131. bypassdrag = true
  132. return
  133. }
  134. swipestart = true
  135. var mousey = e.pageY
  136. dy = 0 // reset swipe amount
  137. if (translatesupport){
  138. $wrapper.css({transition: 'none'})
  139. }
  140. var initialy = -$window.outerHeight() * selectedindx
  141. $wrapper.data({dy: dy})
  142. $(document).bind(swipeevts.move, function(e){
  143. if (bypassdrag){
  144. return
  145. }
  146. var e = (e.type.indexOf('touch') != '-1')? e.originalEvent.changedTouches[0] : e
  147. dy=e.pageY-mousey //distance to move horizontally
  148. var newy=initialy+dy
  149. newy = applybounds(newy, (dy < 0)? 'down' : 'up')
  150. if (translatesupport){
  151. $wrapper.css('transform', 'translate3d(0, ' + newy + 'px, 0)')
  152. }
  153. else{
  154. $wrapper.css('top', newy)
  155. }
  156. $wrapper.data({dy: dy})
  157. return false //cancel default drag action
  158. })
  159. if (e.type == "mousedown")
  160. return false //cancel default drag action
  161. })
  162. $(document).bind(swipeevts.end, function(e){
  163. $(document).unbind(swipeevts.move)
  164. if (!swipestart || bypassdrag)
  165. return
  166. if (dy != 0){ // if actual swipe has occured
  167. if (dy < 0 && dy < -s.swipeconfig.peekamount) // if swipe down and more than peek amount
  168. var targetindx = Math.min(slideslength-1, selectedindx+1)
  169. else if (dy > 0 && dy > s.swipeconfig.peekamount) // if swipe up and more than peek amount
  170. var targetindx = Math.max(0, selectedindx-1)
  171. else
  172. targetindx = selectedindx
  173. thisslider.slideTo(targetindx)
  174. if (e.type == "mouseup")
  175. return false
  176. }
  177. swipestart = false
  178. })
  179. /** CSS3 transition ontransitionend event set up */
  180. $wrapper.on('transitionend webkitTransitionEnd', function(e){
  181. if (/transform/i.test(e.originalEvent.propertyName)){ // check event fired on "transform" prop
  182. onslidealways($slides.eq(selectedindx), selectedindx)
  183. }
  184. })
  185. /** Public functions **/
  186. this.reloadSlides = function(){
  187. $nav.remove()
  188. hasharray = []
  189. $nav = $('<ul class="fssnav" />')
  190. $slides = $('article.slide').each(function(i){
  191. var $curslide = $(this)
  192. var anchorval = $curslide.attr('id') || 'slide' + (i+1)
  193. anchorval = "#" + anchorval
  194. hasharray.push([anchorval, i])
  195. var title = $curslide.data('title') || anchorval
  196. var $navli = $('<li><a href="' + anchorval +'" title="' + title +'">' + (i + 1) + '</a></li>').appendTo($nav)
  197. var $navlink = $navli.find('a:eq(0)')
  198. $navli.on('click touchstart', function(e){
  199. thisslider.slideTo(i)
  200. })
  201. })
  202. $nav.on('click touchstart touchend', function(e){
  203. var e = (e.type.indexOf('touch') != '-1')? e.originalEvent.changedTouches[0] : e
  204. return false
  205. }).appendTo($slider)
  206. slideslength = $slides.length
  207. bounds = [0, $window.outerHeight() * (slideslength-1)]
  208. }
  209. this.openSlider = function(){
  210. initialrun = false
  211. bypassdrag = false
  212. s.sliderstate = 'open'
  213. $root.addClass('fssopen')
  214. $slider.css('visibility', 'visible')
  215. }
  216. this.closeSlider = function(){
  217. s.sliderstate = 'close'
  218. bypassdrag = true
  219. $root.removeClass('fssopen')
  220. $slider.css({visibility:'hidden'})
  221. }
  222. this.slideTo = function(indx, noanimation){
  223. var newy = $window.outerHeight() * indx
  224. $nav.find('li').eq(selectedindx).removeClass('selected')
  225. $nav.find('li').eq(indx).addClass('selected')
  226. selectedindx = indx
  227. if (translatesupport){
  228. $wrapper.css({transition: (noanimation)? 'none' : transformprop + ' ' + s.transitionDuration})
  229. $wrapper.css('transform', 'translate3d(0, -' + newy + 'px, 0)')
  230. if (noanimation){ // run callback immediately
  231. onslidealways($slides.eq(selectedindx), selectedindx)
  232. }
  233. }
  234. else{
  235. $wrapper.stop().animate({top: -newy}, (noanimation)? 0 : s.transitionDuration, function(){
  236. onslidealways($slides.eq(selectedindx), selectedindx)
  237. })
  238. }
  239. }
  240. /** Initialize and show slider **/
  241. this.reloadSlides()
  242. selectedindx = hashtoselectedslide(window.location.hash)
  243. this.slideTo(selectedindx, true)
  244. if (s.sliderstate == 'open'){
  245. this.openSlider()
  246. }
  247. $(window).on('resize', function(){
  248. thisslider.slideTo(selectedindx, true)
  249. bounds = [0, $window.outerHeight() * (slideslength-1)]
  250. })
  251. } // end ddfullscreenslider def
  252. return ddfullscreenslider
  253. })(jQuery)