Reputation: 797
I have side dot navigation on website - standard position: fixed
dot nav. Now i have also 2 types of sections with 2 types of background on same website - lets assume one are white and another black. My problem is that when dots are not visible when navigation is hovering black section. So i tried to write script that detects if section have certain class and if certain dot is on this section - if yes then color of dot is changed. I had certain success but after i finish i realise that my script works only in one way ( scrolling top to bottom ) and even if i will detect bottom to top scrolling it will not work properly when i change direction in the middle of website. I arleady spend on this quite a while and im clueless - here is code that i have so far - its working when you scroll from top to bottom.
Do you have any other suggestion or perhaps some library to solve this issue ?
EDIT: Layout is quite artistic - so there are some boxes that floats from left or right dynamicly and dots also have to change when box is there, its why i splice my array and push #myname
to it.
EDIT2: You can see how it works under this link ( not optimized, slow load time http://lektor.ionstudio.pl/)
var sections = [];
$("section[id]").each(function() {
sections.push("#" + this.id);
})
sections.splice(0,0,"#myname");
i = 0;
$(window).scroll(function(){
var content = $("section.current").hasClass("white-section");
$("#banner .navigation li").each(function(){
var thisElem = this.getBoundingClientRect();
section = sections[i];
section = document.querySelector(section);
sectionRect = section.getBoundingClientRect();
if(sectionRect.top - thisElem.top <= 0) {
if($(section).hasClass("white")) {
$(this).addClass("black");
} else {
$(this).removeClass("black");
}
if(sectionRect.top + $(section).outerHeight(true) <= thisElem.top ) {
i++;
}
}
})
})
Upvotes: 2
Views: 101
Reputation: 14267
As mentioned in the comments i would use elementFromPoint
to check if a dot it over a section with a specific class.
Try this:
(function(win, doc) {
var dotsSelector = '.dot';
var sectionsSelector = 'section';
var classes = ['white', 'black'];
var dots = [].slice.call(doc.querySelectorAll(dotsSelector));
var dotPositions = dots.map(function(dot) {
var rect = dot.getBoundingClientRect();
return rect.top + rect.height / 2 ;
});
var sections = [].slice.call(doc.querySelectorAll(sectionsSelector));
win.addEventListener('scroll', function(event) {
for(var i = 0; i < dots.length; ++i) {
var element = doc.elementFromPoint(0, dotPositions[i]);
var section = null;
while(!section && element) {
section = sections.find(function(s) { return s === element });
element = element.parentNode;
}
if(section) {
dots[i].classList.toggle(classes[0], section.classList.contains(classes[1]));
}
}
});
})(window, document);
section {
min-height: 400px;
background: white;
}
section.black {
background: black;
}
.menu {
position: fixed;
top: 50%;
transform: translateY(-50%);
left: 10px;
z-index: 20;
}
.dot {
border-radius: 50%;
width: 20px;
height: 20px;
background: black;
margin-bottom: 10px;
}
.dot.white {
background: white;
}
* {
padding: 0;
margin: 0;
}
ul {
list-style: none;
}
<section></section>
<section class="black"></section>
<section></section>
<section class="black"></section>
<section></section>
<section class="black"></section>
<ul class="menu">
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
</ul>
Upvotes: 1
Reputation: 101
It only works on one way scroll because of the way you are looping. You need to remove the dependence of the 'i' increment in your function.
The only reason you are using this increment is because you need to be able to uniquely identify the section.
Are you able to add some meta data to "this" element that you could use to identify the section instead? Something like
<li data-sectionID="999" ....>Menu Node</li>
...
section = $(this).data("sectionID");
Upvotes: 0