|
/** |
|
* @version 3.6 - 31.10.2023 |
|
* @author Artem Kuznecov |
|
* @email info@artemsites.ru |
|
* @website https://artemsites.ru |
|
* @source https://snippets.cacher.io/snippet/79e169f9ca705c345531 |
|
* @source https://gist.github.com/artemijeka/130fd58f6859999faafcea60de686262 |
|
* @param {String|Node} obj.target | Блок который фиксируем |
|
* |
|
* Класс --fixed просто добавляется без style изменений (для гибкости) |
|
* @param {Boolean} obj.fixAtTop | Зафиксировать везде начиная с верха сайта |
|
* |
|
* @param {Boolean} obj.fixAfter | Зафиксировать после ухода этого блока за верх экрана |
|
* @param {Array} obj.addClass | Добавить класс к какому-то элементу - addClass: ['.header', '_header-fixed'] |
|
* @param {String} obj.fixUnderBlock | |
|
* @param {String} obj.fixOverBlock | |
|
* @param {Number} obj.marginBottom | |
|
*/ |
|
|
|
/** |
|
new Fixer({ |
|
target: '.header__self', |
|
fixAtTop: true, |
|
addClass: ['.header', '_header-fixed'] |
|
}); |
|
*/ |
|
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; |
|
|
|
if (obj.addClass) { |
|
this.elAddClass = document.querySelector(obj.addClass[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.classList.add('--fixed'); |
|
if (self.elAddClass) self.elAddClass.classList.add(obj.addClass[1]); |
|
self.fixed = true; |
|
} else if ( |
|
self.fixed && |
|
self.windowOfTop < self.targetOffsetTopFixed |
|
) { |
|
self.target.classList.remove('--fixed'); |
|
if (self.elAddClass) self.elAddClass.classList.remove(obj.addClass[1]); |
|
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; |
|
} |
|
} |
|
}); |
|
}); |
|
})(); |
|
} |