viewportchecker.min.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. The MIT License (MIT)
  3. Copyright (c) 2014 Dirk Groenen
  4. Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. this software and associated documentation files (the "Software"), to deal in
  6. the Software without restriction, including without limitation the rights to
  7. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. the Software, and to permit persons to whom the Software is furnished to do so,
  9. subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in all
  11. copies or substantial portions of the Software.
  12. */
  13. (function($){
  14. $.fn.viewportChecker = function(useroptions){
  15. // Define options and extend with user
  16. var options = {
  17. classToAdd: 'visible',
  18. classToRemove : 'invisible',
  19. classToAddForFullView : 'full-visible',
  20. removeClassAfterAnimation: false,
  21. offset: 100,
  22. repeat: false,
  23. invertBottomOffset: true,
  24. callbackFunction: function(elem, action){},
  25. scrollHorizontal: false,
  26. scrollBox: window
  27. };
  28. $.extend(options, useroptions);
  29. // Cache the given element and height of the browser
  30. var $elem = this,
  31. boxSize = {height: $(options.scrollBox).height(), width: $(options.scrollBox).width()};
  32. /*
  33. * Main method that checks the elements and adds or removes the class(es)
  34. */
  35. this.checkElements = function(){
  36. var viewportStart, viewportEnd;
  37. // Set some vars to check with
  38. if (!options.scrollHorizontal){
  39. viewportStart = Math.max(
  40. $('html').scrollTop(),
  41. $('body').scrollTop(),
  42. $(window).scrollTop()
  43. );
  44. viewportEnd = (viewportStart + boxSize.height);
  45. }
  46. else{
  47. viewportStart = Math.max(
  48. $('html').scrollLeft(),
  49. $('body').scrollLeft(),
  50. $(window).scrollLeft()
  51. );
  52. viewportEnd = (viewportStart + boxSize.width);
  53. }
  54. // Loop through all given dom elements
  55. $elem.each(function(){
  56. var $obj = $(this),
  57. objOptions = {},
  58. attrOptions = {};
  59. // Get any individual attribution data
  60. if ($obj.data('vp-add-class'))
  61. attrOptions.classToAdd = $obj.data('vp-add-class');
  62. if ($obj.data('vp-remove-class'))
  63. attrOptions.classToRemove = $obj.data('vp-remove-class');
  64. if ($obj.data('vp-add-class-full-view'))
  65. attrOptions.classToAddForFullView = $obj.data('vp-add-class-full-view');
  66. if ($obj.data('vp-keep-add-class'))
  67. attrOptions.removeClassAfterAnimation = $obj.data('vp-remove-after-animation');
  68. if ($obj.data('vp-offset'))
  69. attrOptions.offset = $obj.data('vp-offset');
  70. if ($obj.data('vp-repeat'))
  71. attrOptions.repeat = $obj.data('vp-repeat');
  72. if ($obj.data('vp-scrollHorizontal'))
  73. attrOptions.scrollHorizontal = $obj.data('vp-scrollHorizontal');
  74. if ($obj.data('vp-invertBottomOffset'))
  75. attrOptions.scrollHorizontal = $obj.data('vp-invertBottomOffset');
  76. // Extend objOptions with data attributes and default options
  77. $.extend(objOptions, options);
  78. $.extend(objOptions, attrOptions);
  79. // If class already exists; quit
  80. if ($obj.data('vp-animated') && !objOptions.repeat){
  81. return;
  82. }
  83. // Check if the offset is percentage based
  84. if (String(objOptions.offset).indexOf("%") > 0)
  85. objOptions.offset = (parseInt(objOptions.offset) / 100) * boxSize.height;
  86. // Get the raw start and end positions
  87. var rawStart = (!objOptions.scrollHorizontal) ? $obj.offset().top : $obj.offset().left,
  88. rawEnd = (!objOptions.scrollHorizontal) ? rawStart + $obj.height() : rawStart + $obj.width();
  89. // Add the defined offset
  90. var elemStart = Math.round( rawStart ) + objOptions.offset,
  91. elemEnd = (!objOptions.scrollHorizontal) ? elemStart + $obj.height() : elemStart + $obj.width();
  92. if (objOptions.invertBottomOffset)
  93. elemEnd -= (objOptions.offset * 2);
  94. // Add class if in viewport
  95. if ((elemStart < viewportEnd) && (elemEnd > viewportStart)){
  96. // Remove class
  97. $obj.removeClass(objOptions.classToRemove);
  98. $obj.addClass(objOptions.classToAdd);
  99. // Do the callback function. Callback wil send the jQuery object as parameter
  100. objOptions.callbackFunction($obj, "add");
  101. // Check if full element is in view
  102. if (rawEnd <= viewportEnd && rawStart >= viewportStart)
  103. $obj.addClass(objOptions.classToAddForFullView);
  104. else
  105. $obj.removeClass(objOptions.classToAddForFullView);
  106. // Set element as already animated
  107. $obj.data('vp-animated', true);
  108. if (objOptions.removeClassAfterAnimation) {
  109. $obj.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){
  110. $obj.removeClass(objOptions.classToAdd);
  111. });
  112. }
  113. // Remove class if not in viewport and repeat is true
  114. } else if ($obj.hasClass(objOptions.classToAdd) && (objOptions.repeat)){
  115. $obj.removeClass(objOptions.classToAdd + " " + objOptions.classToAddForFullView);
  116. // Do the callback function.
  117. objOptions.callbackFunction($obj, "remove");
  118. // Remove already-animated-flag
  119. $obj.data('vp-animated', false);
  120. }
  121. });
  122. };
  123. /**
  124. * Binding the correct event listener is still a tricky thing.
  125. * People have expierenced sloppy scrolling when both scroll and touch
  126. * events are added, but to make sure devices with both scroll and touch
  127. * are handles too we always have to add the window.scroll event
  128. *
  129. * @see https://github.com/dirkgroenen/jQuery-viewport-checker/issues/25
  130. * @see https://github.com/dirkgroenen/jQuery-viewport-checker/issues/27
  131. */
  132. // Select the correct events
  133. if( 'ontouchstart' in window || 'onmsgesturechange' in window ){
  134. // Device with touchscreen
  135. $(document).bind("touchmove MSPointerMove pointermove", this.checkElements);
  136. }
  137. // Always load on window load
  138. $(options.scrollBox).bind("load scroll", this.checkElements);
  139. // On resize change the height var
  140. $(window).resize(function(e){
  141. boxSize = {height: $(options.scrollBox).height(), width: $(options.scrollBox).width()};
  142. $elem.checkElements();
  143. });
  144. // trigger inital check if elements already visible
  145. this.checkElements();
  146. // Default jquery plugin behaviour
  147. return this;
  148. };
  149. })(jQuery);