Highlight menu item on scroll does not work - javascript

The problem I have is the next one:
Only the last section of my code add the class, but the rest not.
Each section of my html has a unique class and the same class is also in the list tags
const activ = () => {
const linkMenus = document.querySelectorAll('a')
sections.forEach(clas => {
const view = clas.getBoundingClientRect()
if (view.top < 50 && view.top >= -800){
clas.classList.add("active");
linkMenus.forEach(lis => {
if (clas.classList.contains("active") &&
lis.classList.contains(clas.id)){
lis.classList.add("active_nav");
}
else {
lis.classList.remove("active_nav");
}
})
}
else{
clas.classList.remove("active");
}
})
};
window.addEventListener('scroll', activ)

I made this idea before, I will put my HTML, CSS and JS code, you can read it and use the JS code, maybe it will help you.
you can see the code on Codepen or use the snippet.
If you have any question, ask me.
Focus on this code in the JavaScript:
window.scrollY > sections[i].offsetTop && window.scrollY < sections[i].offsetTop + sections[i].offsetHeight
Snippet:
var sections = document.getElementsByTagName("section"),
li = document.getElementsByClassName("li"),
i;
window.onscroll = function () {
for ( i = 0 ; i < sections.length ; i = i + 1 ) {
if ( window.scrollY > sections[i].offsetTop && window.scrollY < sections[i].offsetTop + sections[i].offsetHeight ) {
li[i].classList.add("red");
sections[i].classList.add("red");
} else {
li[i].classList.remove("red");
sections[i].classList.remove("red");
}
}
}
body
{
margin:0;
padding:0;
font-family:sans-serif;
height:2800px;
background:#ccc;
}
.fixed
{
position:fixed;
width:300px;
height:200px;
background:#ccc;
right:20px;
top:50px;
padding:20px;
box-sizing:border-box;
}
.fixed ul
{
margin:0;
padding:0;
}
.fixed ul li
{
line-height:40px;
list-style-type:none;
font-size:25px;
font-weight:bold;
}
section
{
width:100%;
height:600px;
background:yellowgreen;
box-sizing:border-box;
border:4px solid;
margin-top:25px;
line-height:600px;
font-size:40px;
text-align:center;
font-weight:bold;
}
.red
{
color:red;
}
<div class="fixed">
<ul>
<li class="li">one</li>
<li class="li">two</li>
<li class="li">three</li>
<li class="li">four</li>
</ul>
</div>
<section>one</section>
<section>two</section>
<section>three</section>
<section>four</section>

Related

Scroll from div to next div (different height)

I have got page with 5 div's. My div's have different heigh (it's adaptive). How I can go to next div by mouse when I scroll half of the current div?
I trying fullpage.js and onepage.js but it not working for me, because my div must be different height
#first {
width:100vw;
height:700px;
background-color:lightyellow;
text-align:center;
}
#second {
width:100vw;
height:700px;
background-color:lightblue;
text-align:center;
}
#third {
width:100vw;
height:1000px;
background-color:lightpink;
text-align:center;
}
#fourht {
width:100vw;
height:1500px;
background-color:lightgreen;
text-align:center;
}
#fiveth {
width:100vw;
height:800px;
background-color:lightgray;
text-align:center;
}
<div id="first">1 div</div>
<div id="second">2 div</div>
<div id="third">3 div</div>
<div id="fourht">4 div</div>
<div id="fiveth">5 div</div>
you're need get the height current active elem, and give for container transform translate( 0, -height ) on scroll, onepage and fullpage for there are work with this.
var $container = $('.container');
var $elem = $container.find('.elem');
var $active = $container.find('.active').height();
$(window).on('scroll',function(){
$container.css({"transform":"translate(0, -" + $active + "px)"});
});
body{
height: 100%;
}
.container{
transition: 1s all;
}
#first {
width:100vw;
height:700px;
background-color:lightyellow;
text-align:center;
}
#second {
width:100vw;
height:700px;
background-color:lightblue;
text-align:center;
}
#third {
width:100vw;
height:1000px;
background-color:lightpink;
text-align:center;
}
#fourht {
width:100vw;
height:1500px;
background-color:lightgreen;
text-align:center;
}
#fiveth {
width:100vw;
height:800px;
background-color:lightgray;
text-align:center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div id="first" class="elem active">1 div</div>
<div id="second" class="elem">2 div</div>
<div id="third" class="elem">3 div</div>
<div id="fourht" class="elem">4 div</div>
<div id="fiveth" class="elem">5 div</div>
</div>
I created my version. Look at this https://codepen.io/damates/pen/VXdKjR .
Jquery:
$("#nextDiv, #previousDiv").click(function(){
actualTopOffset = $(window).scrollTop();
areas = $(".area");
find = false;
newPosition = 0;
type = $(this).attr("data-type");
areasCount = $(areas).length;
$.each(areas, function(index, val) {
if(type == "next"){//if we click to go next area
if($(areas).length > (index+1)){
if(actualTopOffset < $(areas[index+1]).offset().top && !find){// ask if area has top offset higher. If yes set new position
find = true;
newPosition = $(areas[index+1]).offset().top;
}
}
}else if(type == "prev"){ //if we click to go previous area
areasCount--;
if((areasCount) >= 0){
if(actualTopOffset > $(areas[areasCount]).offset().top && !find){// ask if area has top offset lower. If yes set new position
find = true;
newPosition = $(areas[areasCount]).offset().top;
}
}
}
});
if(find){ //If we found new position scroll on new position
$('html, body').animate({
scrollTop: newPosition
}, 1000);
}
});
CSS:
#first {
width:100vw;
height:700px;
background-color:lightyellow;
text-align:center;
}
#second {
width:100vw;
height:700px;
background-color:lightblue;
text-align:center;
}
#third {
width:100vw;
height:1000px;
background-color:lightpink;
text-align:center;
}
#fourht {
width:100vw;
height:1500px;
background-color:lightgreen;
text-align:center;
}
#fiveth {
width:100vw;
height:800px;
background-color:lightgray;
text-align:center;
}
#nextDiv, #previousDiv{
position: fixed;
top: 20px;
background: red;
}
#previousDiv{
top: 0px;
}
HTML:
<div id="first" class="area">1 div</div>
<div id="second" class="area">2 div</div>
<div id="third" class="area">3 div</div>
<div id="fourht" class="area">4 div</div>
<div id="fiveth" class="area">5 div</div>
<div id="previousDiv" data-type="prev">Previous div</div>
Next div
EDIT VERSION WITH SCROLL
I change the script for scrolling. Look at to https://codepen.io/damates/pen/VXdKjR

JavaScript animation hanging up

I have an animation build with setInterval.
function changeBatteryIcon(status, i) {
switch (status) {
case 1:
i.className = "fa fa-battery-half red"
return ++status
case 2:
i.className = "fa fa-battery-3 orange"
return ++status
case 3:
i.className = "fa fa-battery lightgreen"
return 1
}
}
function animateHeaderBatteries() {
const i =
document.getElementById("header-batteries").querySelector('i')
let status = 1
setInterval(function() {
status = changeBatteryIcon(status, i)
}, 300)
}
animateHeaderBatteries()
const chargeBtn = document.getElementById('charge')
const drainBtn = document.getElementById('drain')
let ammount = 1
let not = document.getElementById('battery-not')
function charge(battery_charge) {
if (ammount == 1) {
const intervalHandler =
setInterval(function() {
++ammount
const style = `width:${ammount}%;`
battery_charge.style = style
changeStyle(ammount)
if (ammount == 100) {
clearInterval(intervalHandler)
not.style = 'background-color:lightgreen'
}
}, 50)
}
}
function drain(battery_charge) {
if (ammount == 100) {
const intervalHandler =
setInterval( function() {
--ammount
const style = `width:${ammount}%`
battery_charge.style = style
changeStyle(ammount)
if (ammount < 100) {
not.style = 'background-color:white'
}
if (ammount == 1) {
clearInterval(intervalHandler)
}
}, 50)
}
}
const battery_charge = document.getElementById('battery-charge')
function changeStyle (ammount) {
if (ammount > 25)
battery_charge.style['background-color'] = 'orange'
if (ammount > 50)
battery_charge.style['background-color'] = 'yellow'
if (ammount > 75)
battery_charge.style['background-color'] = 'lightgreen'
}
chargeBtn.onclick = function () {
charge(battery_charge)
}
drainBtn.onclick = function () {
drain(battery_charge)
}
body {
font-family:arial;
}
.red {
color:red;
}
.orange {
color:orange;
}
.lightgreen {
color:lightgreen;
}
header {
flex-direction:column;
display:flex;
align-items:center;
justify-content:center;
background-color:#252525;
color:yellow;
}
#header-batteries {
padding-top:20px;
}
header h1 {
margin-top:0;
}
article {
display:flex;
flex-direction: column;
justify-content:center;
align-items:center;
}
#battery-container {
width:50%;
margin-top:20px;
margin-bottom:20px;
display:flex;
align-items:center;
}
#battery {
border:2px solid #252525;
height:75px;
width:90%;
display:flex;
align-items:center;
}
#battery-not {
height:25px;
border:2px solid black;
border-left:0;
width:2%;
}
#battery-charge {
height:100%;
width:1%;
background-color:red;
display:flex;
}
#bolt {
position:absolute;
left:45%;
font-size:50px;
color:grey;
}
#controls {
width:50%;
display:flex;
justify-content:flex-end;
}
#controls button {
height:40px;
flex-basis:40%;
background-color:#f2f200;
border:0;
font-size:16px;
font-weight:bold;
font-family:Helvetica;
margin-left:10px;
}
footer {
display:flex;
align-items:center;
justify-content:center;
margin-top:50px;
}
<html lang="pt-BR">
<meta charset="UTF-8">
</html>
<body>
<div id="container">
<header>
<div id="header-batteries">
<i class="fa fa-battery"></i>
</div>
<h1>Battery</h1>
</header>
<article>
<div id="battery-container">
<div id="battery">
<i class="fa fa-bolt" id="bolt"></i>
<div id="battery-charge">
</div>
</div>
<div id="battery-not">
</div>
</div>
<div id="controls">
<button id="charge">
CHARGE
</button>
<button id="drain">
DRAIN
</button>
</div>
</article>
<footer>
<span>Made with <i class="fa fa-heart red" ></i> by Alex Alonso</span>
</footer>
</div>
</body>
It should run smoothly, changing the css and thus animating the battery charge. But what happens is that it hangs up a little bit in the beginning, but only at the first cycle of animation. After that all animations run smoothly.
const intervalHandler =
setInterval(function() {
++ammount
console.log(ammount)
const style = `width:${ammount}%;`
battery_charge.style = style
changeStyle(ammount)
if (ammount == 100) {
clearInterval(intervalHandler)
not.style = 'background-color:lightgreen'
}
}, 50)
I want to know why it behaves like this
Try using requestAnimationFrame as it is the recommended way as compared to other options to do stuff like animations etc.

Change navigation font color based on background

My problem is this. I have a fixed left navigation bar and I have to change the list font color based on the background of the section under it. The code is like this fiddle. So if the section is black and is below a link, the text is not seen. I have to change each list based on the background of a section under it so that it can be readable.
html
<div class="content">
<div id="left_side">
<div id="static_menu" class="">
<div id="main_navigation" class="">
<ul class="menu mainLeft" id="mymenu">
<li>Nav list 1</li>
<li>Nav list 2</li>
<li>Nav list 3</li>
<li>Nav list 4</li>
<li>Nav list 5</li>
</ul>
</div>
</div>
</div>
<div id="wrapper">
<div class="section" id="section1">section1</div>
<div class="section" id="section2">section2</div>
<div class="section" id="section3">section3</div>
<div class="section" id="section4">section4</div>
<div class="section" id="section5">section5</div>
</div>
</div>
css
.content{
position:relative;
}
#left_side
{
position:fixed;
left: 20px;
right: 20px;
z-index:999;
}
.mainLeft
{
list-style-type:none;
margin-left:0px;
padding-left:0px;
}
.mainLeft li
{
padding:5px 0;
}
.mainLeft li a
{
color:#000;
margin-bottom:5px;
}
#wrapper
{
position:relative;
}
.section
{
width: 100%;
text-align:center;
padding:150px 0;
border:1px solid #666;
}
#section1
{
background: #fff;
}
#section2
{
background: #000;
color:#fff;
}
#section3
{
background: #fff;
}
#section4
{
background: #000;
color:#fff;
}
#section5
{
background: #fff;
}
Fiddel
To do what you asked for you can do this with jquery:
working fiddle
var _li, _sections;
$(function() {
_li = $("#mymenu").find("li");
_sections = $("#wrapper").find(".section");
$(window).on('scroll', liBgs);
});
function liBgs() {
for (var i = 0; i < _li.length ; i++) {
var _litop = _li.eq(i).offset().top;
for (var j = 0; j < _sections.length; j++) {
var $s = _sections.eq(j),
_sectop = $s.offset().top,
_secbottom = $s.offset().top+$s.height()-20;
if (_litop > _sectop && _litop > _secbottom) {
var _color = rgb2hex($s.css('background-color'));
_li.eq(i).find('a').css('color', (_color=="#ffffff") ? "#000000" : "#ffffff");
}
}
}
}
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
NOTE: rgb2hex() function was taken from this question: How to get hex color value rather than RGB value?
What this code does:
I'm basically comparing positions of the menu li's to the sections, checking under what
section each li is over everytime you scroll.. I'm not sure this is very efficient, but for something small scale it's ok.. if anyone knows how to make this even more efficient I'll be happy to learn.
Used jquery to do this. Found a reference here
HTML:
Added a extra attribute of color
<div class="section" id="section1" data-color="#333">section1</div>
JS:
$(window).on('scroll', function() {
var scrollTop = $(this).scrollTop();
$('.section').each(function() {
var topDistance = $(this).offset().top;
if ( (topDistance) < scrollTop ) {
$('#mymenu a').css('color',$(this).attr('data-color'));
}
});
});
DEMO
Can't you just give it a neutral colour to the fixed div and make it wrap around its content rather than have to resort to client scripts to dynamically change the colour? I have sanitized a bit the fixed element to make it look a bit more appealing...padding, margins, etc.
#left_side
{
position:fixed;
left: 20px;
top:10px;
z-index:999;
background-color:#eee;
padding:10px;
}
JS Fiddler Example
Something like this would work:
$(window).scroll(function() {
/* get current scroll-position within window */
var scroll = $(window).scrollTop();
$('.mainLeft li').each(function() {
/* get position of navigation-element (distance from top minus half of it's height, so that it changes color while it's half over black and half over white background) */
var elementPositionTop = parseFloat($(this).offset().top) + (parseFloat($(this).height() / 2));
/* change color for each background-change */
if (elementPositionTop >= 320 && elementPositionTop <= 640 || elementPositionTop >= 960 && elementPositionTop <= 1280) {
$(this).addClass('whiteText');
} else {
$(this).removeClass('whiteText');
}
});
});
Here's the additional CSS:
.mainLeft li.whiteText a {
color: #fff;
}
.section {
height: 18px;
overflow: hidden;
}
I gave the .section divs a fixed height because the JS I used works with fixed pixel values, and not all browsers interpret the height of elements the same if they're not defined...
Here's a fiddle: http://jsfiddle.net/Niffler/z34cG/
Updated.. see this fiddle
Do u Mean like this
$(document).scroll(function(){
var top=$(document).scrollTop()-322;
console.log(top)
if(top<0)
{
$('.mainLeft li a').css('color','black')
$('#li1 a').css('color',$('#section1').css('color'))
//$('#li1 a').css('color',"red")
}
if(top>0 && top<322)
{
$('.mainLeft li a').css('color','black')
$('#li2 a').css('color',$('#section2').css('color'))
//$('#li1 a').css('color',"red")
}
if(top>322 && top<644)
{
$('.mainLeft li a').css('color','black')
$('#li3 a').css('color',$('#section3').css('color'))
//$('#li1 a').css('color',"red")
}
if(top>644 && top<966)
{
$('.mainLeft li a').css('color','black')
$('#li4 a').css('color',$('#section4').css('color'))
//$('#li1 a').css('color',"red")
}
if(top>966 && top<1288)
{
$('.mainLeft li a').css('color','black')
$('#li5 a').css('color',$('#section5').css('color'))
//$('#li1 a').css('color',"red")
}
});

Explore generic value like WebKit console

I am developing a customed tool to test a javascript library.
I'm using Chrome.
I need to explore a generic object, programmaticaly, like WebKit console, when I write "window" and press enter.
How can I implement that inspector?
Or, how can I invoce that object inspector and insert generated HtmlElement to DOM?
In waiting I develop the Explore method.
jQuery required.
This is the JavaScript code:
window.Debugger = {};
window.Debugger.Explore = function (value) {
var fReturn = jQuery("<div class=\"DbgExp\" />");
if (value === null) {
fReturn.addClass("aNull").text("null");
} else {
switch (typeof value) {
case "undefined":
fReturn.addClass("aNull").text("undefined");
break;
case "string":
fReturn.addClass("aStr").text("\"" + value + "\"");
break;
case "number":
fReturn.addClass("aVal").text(value);
break;
case "boolean":
fReturn.addClass("aVal").text(value ? "true" : "false");
break;
case "function":
case "object":
var str1 = "" + value;
if (str1.length > 40) str1 = str1.substr(0, 37) + "...";
var objName = jQuery("<div class=\"name\" />").text(str1);
fReturn.addClass("aObj").append(objName);
objName.click(function (ev, data) {
if (fReturn.hasClass("aOn")) return fReturn.removeClass("aOn");
fReturn.addClass("aOn");
if (fReturn.data("isFill")) return;
var ul = jQuery("<ul />").appendTo(fReturn);
var num = 0;
for (var k in value) {
jQuery("<li />")
.appendTo(ul)
.append(
jQuery("<div class=\"lbl\" />").text(k)
, Debugger.Explore(value[k])
);
num++;
}
if (num == 0) {
jQuery("<li><div class=\"lbl\">- no properties -</div></li>").appendTo(ul);
}
fReturn.data("isFill", true);
});
break;
}
}
return fReturn;
};
And this is the CSS:
.DbgExp { display:inline-block; background-color:white; color:black; font-family:monospace; font-size:10pt; }
.DbgExp.aNull { background-color:white; font-size:10pt; color:#a9a9a9; }
.DbgExp.aStr { background-color:white; font-size:10pt; color:#a62222; }
.DbgExp.aVal { background-color:white; font-size:10pt; }
.DbgExp.aObj { background-color:white; font-size:10pt; border:dotted 1px cornflowerblue; margin-left:20px; }
.DbgExp.aObj:before { display:inline-block; content:"+"; background-color:#d8eaff; border:solid 1px #0966b4; width:16px; line-height:16px; font-family:monospace; font-size:14px; font-weight:bold; text-align:center; }
.DbgExp.aObj .name { display:inline; font-family:monospace; min-width:40px; margin-left:5px; color:#0966b4; background-color:#d8eaff; border:solid 1px #0966b4; font-size:9pt; font-family:helvetica; padding:1px 4px; cursor:pointer; }
.DbgExp.aObj.aOn:before { content:"-"; }
.DbgExp.aObj ul { display:none; }
.DbgExp.aObj.aOn > ul { display:block; }
.DbgExp.aObj ul li { }
.DbgExp.aObj ul li .lbl { display:inline-block; font-family:helvetica; min-width:80px; font-size:10pt; color:#777; vertical-align:top; }
.DbgExp.aObj ul li .DbgExp { margin-left:10px; }
A html fragment to show how to use:
...
<div id="DebugOutput">
</div>
<script type="text/javascript">
jQuery(document)
.ready(function () {
jQuery("#DebugOutput")
.append(
Debugger.Explore(new Date())
, Debugger.Explore(window)
);
});
</script>

Accessible jQuery toggles odd behaviour

I'm setting up a reusable jQuery toggle function (for my employer) to enable show/hide of content (eg FAQs), to improve accessibility over existing inline onClick bindings.
In JSFiddle everything is fast and fluid, but when I transfer to the preview server an odd behaviour becomes apparent. Clicking the button works as normal, but on clicking the button's link text there's a noticeable delay before anything happens.
Is there anything within the script that might be causing the delay? Or anything which is an obvious candidate for conflicts of some kind?
Anyway, here's the code (based on Mike Raynham's accessible toggles):
http://jsfiddle.net/internet_man/9yKKM/2/
html:
<div class="buttons">
<ul>
<li><strong class="_toggle type noscript">This is the first toggle</strong>
<ul class="_toggle-this show-hide">
<li><strong>Option One</strong></li>
<li><strong>Option Two</strong></li>
<li><strong>Option Three</strong></li>
</ul>
</li>
<li class="bad-break"><strong class="_toggle type noscript">This is the second toggle (a bit longer than the first)</strong>
<ul class="_toggle-this show-hide">
<li><strong>Option One</strong></li>
<li><strong>Option Two</strong></li>
</ul>
</li>
<li class="bad-break"><strong class="_toggle type noscript">This is the third toggle (also somewhat longer)</strong>
<ul class="_toggle-this show-hide">
<li><strong>Option One</strong></li>
<li><strong>Option Two</strong></li>
</ul>
</li>
</ul>
</div>
Script:
var create_name = function(text) {
var name = text.toLowerCase();
name = name.replace(/^\s+|\s+jQuery|[^a-z0-9&\s-]/g, '');
name = name.replace(/&/g, 'and');
name = name.replace(/\s/g, '-');
name = name.replace(/(-)+\1/g, "jQuery1");
return name;
};
var add_link = function() {
var name = create_name(jQuery(this).text());
jQuery(this).next('.toggle-this').attr('name', name);
jQuery(this).html('' + jQuery(this).html() + '');
};
var toggle = function(event) {
event.preventDefault();
jQuery(this).toggleClass('expanded').nextAll('.toggle-this').slideToggle(100);
jQuery('.toggle-this').not(jQuery(this).siblings()).slideUp(100);
jQuery('.toggle').not(jQuery(this)).removeClass('expanded');
};
var remove_focus = function() {
jQuery(this).blur();
};
jQuery(function (){
jQuery('._toggle').removeClass('_toggle, noscript').addClass('toggle');
jQuery('._toggle-this').removeClass('_toggle-this').addClass('toggle-this');
jQuery('._expanded').removeClass('_expanded').addClass('expanded');
jQuery('.toggle:not(.expanded)').nextAll('.toggle-this').hide();
jQuery('.toggle').each(add_link);
jQuery('.toggle').click(toggle);
jQuery('.toggle a').mouseup(remove_focus);
});
CSS:
body
{
font-size:62.5%;
color:#666;
font-family:arial,Helvetica,sans-serif;
}
a
{
color:#462170;
}
ul
{
list-style-type:none;
margin-left:0;
padding-left:0;
}
strong
{
font-weight:normal;
}
div.buttons
{
width:462px;
line-height:2.2em;
margin:1.5em 0;
}
.buttons li > strong
{
font-size:1.9em;
}
.toggle, .buttons .type.noscript
{
display:block;
font-size:1.9em;
height:65px;
background:url(http://oi48.tinypic.com/dy6xf.jpg) 0 -85px no-repeat;
padding:20px 0 0 90px;
text-decoration:none;
color:#462170;
cursor:pointer;
cursor:hand;
}
.toggle a
{
text-decoration:none;
}
.toggle strong
{
display:block;
height:65px;
border:1px dotted red;
}
.toggle:hover, .toggle:focus
{
background-position:0 0;
}
.buttons .show-hide
{
border-bottom:6px solid white;
}
.buttons .show-hide li
{
margin-left:12px;
border-bottom: 2px solid white;
border-top:2px solid white;
font-size:1em;
}
.buttons .show-hide a
{
display:block;
height:15px;
text-decoration:none;
color:#462170;
background:#f1f1f1 url(http://oi46.tinypic.com/6iedtw.jpg) 5px 14px no-repeat;
padding:12px 0 15px 58px;
}
.buttons .show-hide a:hover, .connection-buttons .show-hide a:focus
{
text-decoration:underline;
color:black;
background-color:#ece8f0;
background-position:5px -41px;
}
li.bad-break a
{
padding-right:30%;
}
Notes:
Scripts on -- ._toggle becomes .toggle, ._toggle-this becomes .toggle-this, .noscript is removed and a link is inserted around (in this case) the strong element of class toggle, pointing to the next '.toggle-this' element.
Scripts off -- No toggle created but it's styled as though the accordions are expanded.

Categories

Resources