|
/** |
|
* @version 3.5 - 21.02.2023 |
|
* @author Artem Kuznecov |
|
* @email artem@web-ascent.ru |
|
* @website https://web-ascent.ru |
|
* @source https://snippets.cacher.io/snippet/79e169f9ca705c345531 |
|
* @source https://gist.github.com/artemijeka/130fd58f6859999faafcea60de686262 |
|
* @param {String|Node} obj.target | Блок который фиксируем |
|
* @param {Boolean} obj.fixAtTop | Зафиксировать везде начиная с верха сайта |
|
* @param {Boolean} obj.fixAfter | Зафиксировать после ухода этого блока за верх экрана |
|
* @param {String} obj.fixUnderBlock | |
|
* @param {String} obj.fixOverBlock | |
|
* @param {Number} obj.marginBottom | |
|
*/ |
|
export function Fixer(obj) { |
|
var self = this; |
|
|
|
if (typeof obj.target === 'string') { |
|
this.target = document.querySelector(obj.target); |
|
} else { |
|
this.target = obj.target |
|
} |
|
|
|
this.fixAfter = document.querySelector(obj.fixAfter); |
|
this.windowOfTop = null; |
|
this.targetOfTop = null; |
|
this.targetOffsetTopFixed = null; |
|
// this.height = null; |
|
this.fixed = false; |
|
this.pxOfTop = null; |
|
this.targetAbove = document.querySelector(obj.fixUnderBlock); |
|
this.cssTop = window.getComputedStyle(self.target).getPropertyValue("top"); |
|
this.cssTopNumber = parseFloat(this.cssTop); |
|
this.marginBottomPx = obj.marginBottom || 0; |
|
|
|
this.loopLoadScrollResizeWindow = (function () { |
|
["load", "scroll", "resize"].forEach(function (event) { |
|
window.addEventListener(event, function () { |
|
self.windowOfTop = window.scrollY; |
|
// this.height = self.target.height; |
|
self.targetOfTop = self.target.offsetTop; |
|
|
|
if (obj.fixAfter) { |
|
if (self.fixAfter.getBoundingClientRect().top <= 0) { |
|
self.target.classList.add("--fixed"); |
|
} else { |
|
self.target.classList.remove("--fixed"); |
|
} |
|
} |
|
|
|
if (obj.fixAtTop) { |
|
if (!self.fixed && self.windowOfTop > self.targetOfTop) { |
|
self.targetOffsetTopFixed = self.targetOfTop; |
|
self.target.style.position = "fixed"; |
|
self.target.style.top = "0"; |
|
self.target.classList.add('--fixed'); |
|
self.fixed = true; |
|
} else if ( |
|
self.fixed && |
|
self.windowOfTop < self.targetOffsetTopFixed |
|
) { |
|
self.target.style.position = ""; |
|
self.target.style.top = ""; |
|
self.target.classList.remove('--fixed'); |
|
self.fixed = false; |
|
} |
|
} |
|
|
|
if (obj.fixUnderBlock) { |
|
if ( |
|
self.windowOfTop < self.targetAbove.getBoundingClientRect().height |
|
) { |
|
self.target.classList.add("--fixed"); |
|
self.target.style.top = |
|
"calc(" + self.cssTop + " - " + self.windowOfTop + "px)"; |
|
} else { |
|
// self.target.classList.remove('--fixed'); |
|
self.target.style.top = |
|
"calc(" + self.targetAbove.getBoundingClientRect().height + "px)"; |
|
} |
|
} |
|
|
|
if (obj.fixOverBlock) { |
|
var blockAboveOfViewport = document |
|
.querySelector(obj.fixOverBlock) |
|
.getBoundingClientRect(); |
|
var targetHeight = self.target.getBoundingClientRect().height; |
|
var calcTopOfViewport = |
|
blockAboveOfViewport.top - targetHeight - self.marginBottomPx; |
|
|
|
if ( |
|
blockAboveOfViewport.top < |
|
targetHeight + self.cssTopNumber + self.marginBottomPx |
|
) { |
|
self.target.style.top = calcTopOfViewport + "px"; |
|
} else { |
|
self.target.style.top = self.cssTop; |
|
} |
|
} |
|
}); |
|
}); |
|
})(); |
|
} |