sticky-header.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
  2. 'use strict';
  3. /* jshint esversion: 6 */
  4. (function (v, undefined) {
  5. 'use strict';
  6. var StickyHeader = function StickyHeader() {
  7. var self = this;
  8. if (!this.setupElements()) {
  9. return false;
  10. }
  11. // rebuild on resize
  12. window.addEventListener('resize', window.VAMTAM.debounce(function () {
  13. requestAnimationFrame(function () {
  14. if (self.active && self.winWidth && window.innerWidth !== self.winWidth) {
  15. self.destroy();
  16. requestAnimationFrame(function () {
  17. self.init();
  18. });
  19. }
  20. });
  21. }, 100), false);
  22. // selective refresh support
  23. if ('undefined' !== typeof wp && wp.customize && wp.customize.selectiveRefresh) {
  24. wp.customize.selectiveRefresh.bind('partial-content-rendered', function (placement) {
  25. if (placement.partial.id && ['header-layout-selective', 'header-height'].indexOf(placement.partial.id) !== -1) {
  26. self.rebuild();
  27. }
  28. });
  29. }
  30. };
  31. StickyHeader.prototype.rebuild = function () {
  32. var self = this;
  33. requestAnimationFrame(function () {
  34. self.destroy();
  35. setTimeout(function () {
  36. requestAnimationFrame(function () {
  37. self.setupElements();
  38. self.init();
  39. });
  40. }, 100);
  41. });
  42. };
  43. StickyHeader.prototype.setupElements = function () {
  44. this.el = {
  45. hbox: document.getElementsByClassName('fixed-header-box')[0],
  46. header: document.querySelector('header.main-header'),
  47. main: document.getElementById('main'),
  48. topNav: document.getElementsByClassName('top-nav')[0]
  49. };
  50. if (!this.el.hbox || !this.el.header || !this.el.main) {
  51. return false;
  52. }
  53. this.prevPos = 0;
  54. this.el.logoWrapper = this.el.hbox.getElementsByClassName('logo-wrapper')[0];
  55. this.layout = this.el.header.classList.contains('layout-logo-menu') ? 'single' : this.el.header.classList.contains('layout-overlay-menu') ? 'overlay' : 'double';
  56. this.typeOver = document.body.classList.contains('sticky-header-type-over');
  57. return true;
  58. };
  59. StickyHeader.prototype.canActivate = function () {
  60. return !this.active && (document.body.classList.contains('sticky-header') || document.body.classList.contains('had-sticky-header')) && !document.body.classList.contains('fl-builder-active') && !VAMTAM_FRONT.is_mobile && !window.matchMedia('(max-width: ' + VAMTAM_FRONT.mobile_header_breakpoint + ')').matches && !document.body.classList.contains('sticky-header-type-below') && this.el.hbox;
  61. };
  62. StickyHeader.prototype.init = function () {
  63. var _this = this;
  64. // if we can't activate the sticky header - reset it so that it doesn't overlap anything
  65. if (!this.canActivate()) {
  66. if (document.body.classList.contains('sticky-header')) {
  67. document.body.classList.remove('sticky-header');
  68. document.body.classList.add('had-sticky-header');
  69. if (this.el.hbox && this.el.hbox.style.height === '0px') {
  70. this.el.hbox.style.height = 'auto';
  71. }
  72. }
  73. return;
  74. }
  75. // measure
  76. this.winWidth = window.innerWidth;
  77. this.hboxWidth = this.el.hbox.offsetWidth;
  78. this.hboxHeight = this.el.hbox.offsetHeight;
  79. this.topNavHeight = this.el.topNav ? this.el.topNav.offsetHeight : 0;
  80. this.logoWrapperHeight = this.el.logoWrapper.offsetHeight;
  81. this.hboxOffset = v.offset(this.el.hbox);
  82. this.hboxLeft = this.hboxOffset.left;
  83. var fillerHeight = this.typeOver ? this.topNavHeight : this.hboxHeight;
  84. // mutate
  85. this.el.hboxFiller = this.el.hbox.cloneNode(false);
  86. Object.assign(this.el.hboxFiller.style, {
  87. height: fillerHeight + 'px',
  88. zIndex: 1
  89. });
  90. this.el.hboxFiller.classList.add('hbox-filler');
  91. this.el.hbox.after(this.el.hboxFiller);
  92. // this.hbox loads with height:0px, so we must first reset the height and then measure it again on the next frame
  93. Object.assign(this.el.hbox.style, {
  94. position: this.layout === 'overlay' ? 'fixed' : 'absolute',
  95. top: v.admin_bar_fix + 'px',
  96. left: 0,
  97. width: this.hboxWidth + 'px',
  98. height: '',
  99. 'will-change': 'transform',
  100. transform: 'translateX(' + this.hboxLeft + 'px)'
  101. });
  102. requestAnimationFrame(function () {
  103. _this.hboxHeight = _this.el.hbox.offsetHeight;
  104. _this.resetBottomEdge = Math.max(_this.hboxHeight, _this.el.header.offsetHeight) + _this.hboxOffset.top;
  105. _this.active = true;
  106. });
  107. if (this.el.topNav) {
  108. var topNavFiller = document.createElement('div');
  109. topNavFiller.id = 'top-nav-wrapper-filler';
  110. topNavFiller.style.height = this.topNavHeight + 'px';
  111. this.el.hboxFiller.appendChild(topNavFiller);
  112. }
  113. };
  114. StickyHeader.prototype.destroy = function () {
  115. if (!this.active) {
  116. return;
  117. }
  118. if (this.el.hboxFiller) {
  119. this.el.hboxFiller.remove();
  120. }
  121. Object.assign(this.el.hbox.style, {
  122. position: '',
  123. top: '',
  124. left: '',
  125. width: '',
  126. 'will-change': '',
  127. transform: ''
  128. });
  129. // we don't need to add the classes if the sticky header was disabled in the Customizer
  130. if (document.body.classList.contains('had-sticky-header')) {
  131. document.body.classList.add('sticky-header');
  132. document.body.classList.remove('had-sticky-header');
  133. }
  134. this.active = false;
  135. };
  136. StickyHeader.prototype.measure = function (cpos) {
  137. if (!this.active) {
  138. return;
  139. }
  140. if (this.layout !== 'overlay') {
  141. if (!('blockStickyHeaderAnimation' in v) || !v.blockStickyHeaderAnimation) {
  142. this.direction = this.prevPos === cpos ? '-' : this.prevPos < cpos ? 'down' : 'up';
  143. if (this.direction === 'up' && this.startScrollingUp === undefined) {
  144. // first up
  145. this.startScrollingUp = cpos;
  146. } else if (this.direction === 'down') {
  147. // any down - reset up mark
  148. this.startScrollingUp = undefined;
  149. }
  150. if (this.direction === 'down' && this.startScrollingDown === undefined) {
  151. // first down
  152. this.startScrollingDown = cpos;
  153. } else if (this.direction === 'up') {
  154. // any up - reset down mark
  155. this.startScrollingDown = undefined;
  156. }
  157. this.prevPos = cpos;
  158. }
  159. } else {}
  160. };
  161. StickyHeader.prototype.mutate = function (cpos) {
  162. if (!this.active) {
  163. return;
  164. }
  165. if (this.layout !== 'overlay') {
  166. if (!document.body.classList.contains('no-sticky-header-animation') && !document.body.classList.contains('no-sticky-header-animation-tmp')) {
  167. if (cpos < this.resetBottomEdge + 200) {
  168. // at the top
  169. this.singleRowReset('fast');
  170. } else if (this.direction === 'down' && (cpos - this.startScrollingDown > 30 || cpos < this.resetBottomEdge * 2)) {
  171. // reset header position to absolute scrolling down
  172. this.singleRowReset('slow');
  173. } else if (this.direction === 'up' && (this.startScrollingUp - cpos > 30 || cpos < this.resetBottomEdge * 2)) {
  174. // scrolling up - show header
  175. this.singleRowStick();
  176. }
  177. } else if (document.body.classList.contains('no-sticky-header-animation')) {
  178. // the header should always be in its "scrolled up" state
  179. Object.assign(this.el.hbox.style, {
  180. position: 'fixed',
  181. top: v.admin_bar_fix + 'px',
  182. transform: ''
  183. });
  184. this.el.hbox.classList.toggle('sticky-header-state-stuck', cpos > 0);
  185. this.el.hbox.classList.toggle('sticky-header-state-reset', cpos <= 0);
  186. }
  187. } else {
  188. this.el.hbox.classList.toggle('sticky-header-state-stuck', cpos > 0);
  189. this.el.hbox.classList.toggle('sticky-header-state-reset', cpos <= 0);
  190. }
  191. document.body.classList.toggle('vamtam-scrolled', cpos > 0);
  192. };
  193. StickyHeader.prototype.singleRowReset = function (speed) {
  194. speed = speed || 'fast';
  195. if (!this.active || this.singleRowResetStarted) {
  196. return;
  197. }
  198. this.singleRowResetStarted = true;
  199. var true_reset = function () {
  200. vamtamgs.TweenLite.set(this.el.hbox, {
  201. position: 'absolute',
  202. y: 0,
  203. x: this.hboxLeft
  204. });
  205. this.el.hbox.classList.add('sticky-header-state-reset');
  206. this.el.hbox.classList.remove('sticky-header-state-stuck');
  207. this.singleRowResetStarted = false;
  208. }.bind(this);
  209. window.vamtam_greensock_wait(function () {
  210. vamtamgs.TweenLite.killTweensOf(this.el.hbox);
  211. if (speed === 'fast') {
  212. true_reset();
  213. } else if (speed === 'slow') {
  214. vamtamgs.TweenLite.to(this.el.hbox, 0.15, {
  215. y: -this.hboxHeight,
  216. ease: vamtamgs.Power4.easeOut,
  217. onComplete: true_reset
  218. });
  219. }
  220. }.bind(this));
  221. };
  222. StickyHeader.prototype.singleRowStick = function () {
  223. // it is possible that singleRowStick may be called during a "reset"
  224. // make sure to only stick the header if this.singleRowResetStarted === false
  225. if (!this.active || this.el.hbox.classList.contains('sticky-header-state-stuck') || this.singleRowResetStarted) {
  226. return;
  227. }
  228. this.el.hbox.classList.add('sticky-header-state-stuck');
  229. this.el.hbox.classList.remove('sticky-header-state-reset');
  230. window.vamtam_greensock_wait(function () {
  231. vamtamgs.TweenLite.killTweensOf(this.el.hbox);
  232. vamtamgs.TweenLite.fromTo(this.el.hbox, 0.2, {
  233. position: 'fixed',
  234. top: v.admin_bar_fix,
  235. y: -this.hboxHeight,
  236. x: this.hboxOffset.left
  237. }, {
  238. y: -this.topNavHeight - (this.layout === 'double' ? this.logoWrapperHeight : 0),
  239. ease: vamtamgs.Power4.easeOut
  240. });
  241. }.bind(this));
  242. };
  243. document.addEventListener('DOMContentLoaded', function () {
  244. v.stickyHeader = new StickyHeader();
  245. vamtam_greensock_wait(function () {
  246. v.addScrollHandler(v.stickyHeader);
  247. });
  248. });
  249. })(window.VAMTAM);
  250. },{}]},{},[1]);