Change navigation font color based on background - javascript

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")
}
});

Related

How to trigger a class that is only in view with wapoints

I have multiple sections with the class blockList li throughout each of these sections. How am I able to trigger only the current blockList li items for the ones that are in view? Currently, once any of the list items are in view they all fire throughout the page, even though they are not in view.
The snippet below illustrates the issue I am having.
$('.blockList').waypoint(function() {
$('.blockList li').each(function(index) {
setTimeout(()=>{
$(this).addClass('active');
}, 200*index);
});
}, {
offset: '60%'
});
#blue, #red {
width: 100%;
height: 100vh;
}
#blue {
background: blue;
}
#red {
background: red;
}
.blockList {
margin: 15px 0;
text-align: left;
}
.blockList li {
font-size: 1rem;
color: #FFF;
margin: 20px 0;
opacity: 0;
-webkit-transition: ease 0.4s;transition: ease 0.4s;
-webkit-transform: translateY(-15px);transform: translateY(-15px);
}
.blockList li.active {
opacity: 1;
-webkit-transform: translateY(0px);transform: translateY(0px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/jquery.waypoints.min.js"></script>
<section id="blue">
<ul class="blockList">
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
</section>
<section id="red">
<ul class="blockList">
<li>E</li>
<li>F</li>
<li>G</li>
<li>H</li>
</ul>
</section>
You are adding active class to li items for all of them.
$('.blockList li').each(function(index) {
setTimeout(()=>{
$(this).addClass('active');
}, 200*index);
});
TL:TR
In shorter terms. you are basicaly adding active class two times to each list element. Since you are adding it at the begging and then adding it at the 60% offset.
It loops trough all li and puts active class. So therefore it doesnt have to be in view, since its adding on load.
One solution might be getting position in browser of second object, or make a compact system that it checks all of them, places in array.
So it would check its position -> on scroll check if reached any of the elements -> if reached, add active class to the coresponding ID.
var p = $( "#red" ).position;
var Positions = {top: p.top};
Then get the your center window position
Something like:
jQuery.fn.center = function () {
this.css("position","absolute");
this.css("top", Math.max(0, (($(window).height() - $(this).outerHeight()) / 2) +
$(window).scrollTop()) + "px");
this.css("left", Math.max(0, (($(window).width() - $(this).outerWidth()) / 2) +
$(window).scrollLeft()) + "px");
return this;
}
Then compare them, if it reached the element.
Then get its id and add .active class to the #red li, not genaraly li.
What I would do in this situation:
var global_list = {}; var elemCount = 0;
$(document).ready(function() {
//call initFunc, after its complete, call elimination (so it would check on load) and then set on scroll.
initFunc(function() {
elimination();
$(document).on('scroll', function() { elimination() });
});
//This function is basicaly your startup.
function initFunc(int) {
$('.blockList').each(function() {
var p = $(this).position(); //Lets get its position.
var id = $(this).attr('id'); //Lets get its ID
global_list[id] = p.top; //Lets asign ID -> topPosition, so { first: 8 }...
elemCount++;
});
int();
}
//This assigns needed stuff for allready reached objects.
function elimination() {
if(elemCount != 0) { //Did we allready show all elements?
var cb = $(this).scrollTop() + ($(this).height()), ct = $(this).scrollTop(); //Gets top position, and bottom.
var cP = ct + ((cb - ct)/2); //Gets your center point of viewport - ad half screen size to top;
for(var k in global_list) { //Loop trough all element that are left and see if we did scroll.
if(global_list[k] <= cP) { //Lets check if user scolled to it.
var ic=0;
$('#'+k+' li').each(function() {
setTimeout(()=>{
$(this).addClass('active');
}, 200*ic);
ic++
});
delete global_list[k]; //Lets delete allready assigned classes
elemCount--; //Decreses elements count, so eventualy once all reached, it becomes 0;
}
}
}
}
});
#first {
height: 1000px;
}
#second {
height: 1000px;
}
.beatiful {
background: yellow;
}
.div_div li {
font-size: 1rem;
color: #000;
margin: 20px 0;
opacity: 0;
-webkit-transition: ease 0.4s;transition: ease 0.4s;
-webkit-transform: translateY(-15px);transform: translateY(-15px);
}
.div_div li.active {
opacity: 1;
-webkit-transform: translateY(0px);transform: translateY(0px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='div_div' id='first'>
<ul class="blockList" id='first'>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
</div>
<div class='div_div' id='second'>
<ul class="blockList" id='second'>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
</div>

Attempt to write jQuery fadeTo effect in Javascript

A Website uses only one single jQuery function which we'd like to replace by an equal pure Javascript function. However I struggle to convert (translate) that function.
I am aware jQuery is perfect for that task but the trade-off to download all jQuery code for the few lines of Javascript might be worth the effort - in which I do not succeed.
What the script is doing:
When hovering a sectionBox the all other sectionBox(es) fadeTo a value of 0.4.
The script does NOT utilize IDs assigned to each SectionBox.
The question is: How to handle the equivalent of children and siblings in Javascript?
Update:
After doing some homework I came up with some own functional code which is far from the final Goal to achieve equal functionality and smooth transitions, but at least in its functionality comparable to the existing function in the jQuery code.
Also I rephrased the question(s).
A really great solution using CSS only was provided to solve the problem. However I'd like to learn whether and how I can solve this in pure Javascript.
Currently there are three columns. Left and Center columns are affected by my homework-code whereas the column to the right uses the original jQuery code.
May I suggest to look at the example below to visualize the anticipated Goal.
Here are few Questions:
Q1: How can the functions be combined into less and more efficient functions?
So that hovering an element encompasses all elements in the three columns.
Running the code in Codepen one can observe that when leaving a column (left or center) the last item hovered remains with a value of low opacity.
Q2: How can this behaviour be controlled?
/* --- code to convert ---*/
/*hover left column*/
/*$("#left").children().hover(function() {
$(this).siblings().stop().fadeTo(300,0.4);
$('#center > .sectionBox').stop().fadeTo(300,0.4);
$('#right > .sectionBox').stop().fadeTo(300,0.4);
},
function() {
$(this).siblings().stop().fadeTo(200,1);
$('#center > .sectionBox').stop().fadeTo(200,1);
$('#right > .sectionBox').stop().fadeTo(200,1);
});
*/
/* --- attempt to convert jQuery code from above ---*/
/* --- currently affecting left- and center-columns only --- */
/* --- How to combine functions into less and more efficient functions */
/*
var elem_IDLft = 'left'
var elem_IDCtr = 'center'
var elem_IDRgt = 'right'
*/
/* --- LEFT Column ---*/
var elemLft_ID = 'left'
var elemL_name = document.getElementById(elemLft_ID).children;
var elemL_length = elemL_name.length;
for (var i=0; i<elemL_length; i++) {
elemL_name[i].addEventListener("mouseover", mouseOverL);
elemL_name[i].addEventListener("mouseout", mouseOutL);
}
/*---mouse events---*/
/*---Don't use: style.display = "none"--*/
//function mouseOver() {this.style.opacity = "1.0";}
//function mouseOut() {this.style.opacity = "0.4";}
function mouseOverL() {
for (var i=0; i<elemL_length; i++) {
if (elemL_name[i] === this) {elemL_name[i].style.opacity = "1.0";}
else {elemL_name[i].style.opacity = "0.5";}
}
return;
}
function mouseOutL() {
for (var i=0; i<elemL_length; i++) {
if (elemL_name[i] !== this) {elemL_name[i].style.opacity = "1.0";}
else {elemL_name[i].style.opacity = "0.5";}
}
return;
}
// --- To-Do: smooth Transitions
/* --- CENTER Column ---*/
var elemCtr_ID = 'center'
var elem_name = document.getElementById(elemCtr_ID).children;
var elem_length = elem_name.length;
for (var i=0; i<elem_length; i++) {
elem_name[i].addEventListener("mouseover", mouseOver);
elem_name[i].addEventListener("mouseout", mouseOut);
}
/*---mouse events---*/
/*---Don't use: style.display = "none"--*/
//function mouseOver() {this.style.opacity = "1.0";}
//function mouseOut() {this.style.opacity = "0.4";}
function mouseOver() {
for (var i=0; i<elem_length; i++) {
if (elem_name[i] === this) {elem_name[i].style.opacity = "1.0";}
else {elem_name[i].style.opacity = "0.5";}
}
return;
}
function mouseOut() {
for (var i=0; i<elem_length; i++) {
if (elem_name[i] !== this) {elem_name[i].style.opacity = "1.0";}
else {elem_name[i].style.opacity = "0.5";}
}
return;
}
/* --- Question: How to properly get the inverse for the above 'this' ?---*/
/* --- So that the element 'this' (hovered) has style.opacity = 1 ---*/
/* --- and all others from elem_name get style.opacity = 0.4 --- */
/* --- At the moment it's really bumpy --- */
/* --- Possibly caused by many forced reflows while executing Javascript occur --- */
/* --- The goal is to obtain smooth transitions ---*/
/*-------------------------------------*/
/*--- more jQuery code for columns 'center' and 'right' ---*/
/*--- center column*/
/*
$("#center").children().hover(function() {
$(this).siblings().stop().fadeTo(300,0.4);
$('#left > .sectionBox').stop().fadeTo(300,0.4);
$('#right > .sectionBox').stop().fadeTo(300,0.4);
},
function() {
$(this).siblings().stop().fadeTo(200,1);
$('#left > .sectionBox').stop().fadeTo(200,1);
$('#right > .sectionBox').stop().fadeTo(200,1);
});
*/
/*--- right column*/
$("#right").children().hover(function() {
$(this).siblings().stop().fadeTo(300,0.4);
$('#center > .sectionBox').stop().fadeTo(300,0.4);
$('#left > .sectionBox').stop().fadeTo(300,0.4);
},
function() {
$(this).siblings().stop().fadeTo(200,1);
$('#center > .sectionBox').stop().fadeTo(200,1);
$('#left > .sectionBox').stop().fadeTo(200,1);
});
/*liquid display*/
body {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:62.5%;}
html {font-size:10px; color:#fff; background-color:#242424;}
#wrapper {width: 100%;font-size: 1.2rem; overflow: hidden}
.column {float: left; width: 31.0%; margin-right: 3.5%;} /* 100%-(3*31%)=7%/2=3.5%*/
.last {margin-right: 0;}
h1 {font-size: 1.2rem; text-align:center;padding:-1rem;}
#media screen and (max-width: 800px) {#left.column, #center.column, #right.column {width: 100%;}}
.sectionBox {
background-color: rgba(100,100,100,1.0);
box-shadow: 5px 5px 7px #111;
margin: 0 0 2.0rem 0;
padding: 0.1rem;
}
.sectionBox > p > code {background-color:#efefef; color:#111;}
#left {color:#fffaaa;}
#center {color:#fffccc;}
#right {color:#fffeee;}
<div id="wrapper">
<div class="sectionBox"><h1>Flexbox - fadeTo - transition: from jQuery to pure Javascript</h1>
<p><strong>An attempt to translate this jQuery 'fadeTo'-function to pure Javascript.</strong>
<br />
<code>
/*hover left column*/<br>
$("#left").children().hover(function() {
$(this).siblings().stop().fadeTo(300,0.4);
$('#center > .sectionBox').stop().fadeTo(300,0.4);
$('#right > .sectionBox').stop().fadeTo(300,0.4);
},
function() {
$(this).siblings().stop().fadeTo(200,1);
$('#center > .sectionBox').stop().fadeTo(200,1);
$('#right > .sectionBox').stop().fadeTo(200,1);
});
</code>
</p>
</div>
<div id="left" class="column">id="left"
<section class="sectionBox"><h1>id="newPictures"</h1>
</section>
<section class="sectionBox"><h1>id="oldPictures"</h1>
</section>
<section class="sectionBox"><h1>id="somePlace"</h1>
</section>
<section class="sectionBox"><h1>id="someOtherPlace"</h1>
</section>
</div>
<div id="center" class="column">id="center"
<section class="sectionBox"><h1>id="travelNews"</h1>
</section>
<section class="sectionBox"><h1>id="otherTravelNews"</h1>
</section>
<section class="sectionBox"><h1>id="impressum"</h1>
</section>
</div>
<div id="right" class="column last">id="right"
<section class="sectionBox"><h1>id="search"</h1>
</section>
<section class="sectionBox"><h1>id="toolsFaq"</h1>
</section>
</div>
</div> <!--.wrapper-->
This is the working example of the relevant jQuery code.
/*hover left column*/
$("#left").children().hover(function() {
$(this).siblings().stop().fadeTo(300,0.4);
$('#center > .sectionBox').stop().fadeTo(300,0.4);
$('#right > .sectionBox').stop().fadeTo(300,0.4);
},
function() {
$(this).siblings().stop().fadeTo(200,1);
$('#center > .sectionBox').stop().fadeTo(200,1);
$('#right > .sectionBox').stop().fadeTo(200,1);
});
/*hover center column*/
/*same function for "#center" and "#right" columns*/
... and here is the same code over at codepen.
Link to Codepen
You can use Element.animate()
const div = document.getElementById("animate");
div.onclick = () => {
div.animate({
opacity: 0
}, {
duration: 1000,
easing: "linear",
iterations: 1,
fill: "both"
})
.onfinish = function() {
console.log(div.style.opacity);
}
}
#animate {
width: 50px;
height: 50px;
background: blue;
color: gold;
}
<div id="animate">click</div>
You don't need jQuery for that... and you don't even need javascript either.
pure CSS will do:
/*liquid display*/
body {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:62.5%;}
html {font-size:10px; color:#fff; background-color:#242424;}
#wrapper {overflow: hidden; width: 100%;}
.column {float: left; width: 31.0%; margin-right: 3.5%;} /* 100%-(3*31%)=7%/2=3.5%*/
.last {margin-right: 0;}
#media screen and (max-width: 800px) {#left.column, #center.column, #right.column {width: 100%;}}
.sectionBox {
font-size: 1.6rem;
background-color: rgba(100,100,100,1.0);
box-shadow: 5px 5px 7px #111;
margin: 0 0 1.5rem 0;
padding: 0.5rem 0.3rem 0.5rem 0.3rem;
opacity:1; /* set initial opacity and transition time*/
transition:opacity 200ms ease; /*for when hover-out*/
}
#left {color:#fffaaa;}
#center {color:#fffccc;}
#right {color:#fffeee;}
#wrapper{
pointer-events: none; /*prevents the :hover from firing*/
} /*when not actually on an item */
.sectionBox{
pointer-events:auto; /*resets the hover on the items */
}
#wrapper:hover .sectionBox{
opacity:0.4; /*when hovering the container, all items becomes translucent*/
transition: opacity 300ms ease;
}
#wrapper:hover .sectionBox:hover{
opacity:1; /*prevents the specific hovered item opacity from changing*/
}
<div id="wrapper">
<div id="left" class="column">
<section class="sectionBox"> id="newPictures"
</section>
<section class="sectionBox"> id="oldPictures"
</section>
<section class="sectionBox"> id="somePlace"
</section>
</div>
<div id="center" class="column">
<section class="sectionBox"> id="travelNews"
</section>
<section class="sectionBox"> id="impressum"
</section>
</div>
<div id="right" class="column last">
<section class="sectionBox"> id="search"
</section>
<section class="sectionBox"> id="toolsFaq"
</section>
</div>
</div>
The trick is to use the hover on the container to adjust the opacity of all the childs, while setting the pointer-events to none so it won't fire when not actually over a child.
Then it's just using the hover on the specific child to reset the opacity to 1, and adjusting the transitions.
100% pure CSS magic FTW!

js vertical slider with arrows

The thing is that I need to make a vertical images slider,so that when i press arrow down/arrow up every image changes it's position (the highest one goes bottom,the previous take it's place)
what it should look like:
what i have got so far:
$(function(){
var $vsliderboxes = $('#vsliderboxes'),
$vslidernav = $('#vslidernav'),
boxHeight = $vsliderboxes.height(),
current_index = 0;
function clickslide(){
clearInterval(intervalTimer);
clearTimeout(timeoutTimer);
timeoutTimer = setTimeout(function () {
intervalTimer = window.setInterval(autoslide, 2000);
}, 2500);
var index = $(this).index();
current_index = index;
$vsliderboxes.children().stop().animate({
top : (boxHeight * index * -1)
}, 500);
}
function autoslide(){
current_index++;
if (current_index >= $vsliderboxes.children().children().length) {
current_index = 0;
}
$vslidernav.find('a').eq(current_index).trigger('click');
}
$vslidernav.find('a').click(clickslide);
var intervalTimer = window.setInterval(autoslide, 2000),
timeoutTimer = null;
});
#vslidernav ul {
list-style: none;
padding: 0;
}
#vslidernav ul a {
padding: 0;
cursor: pointer;
height: 50px;
}
#vslidernav ul a:active {
color: #9C9A99;
}
#vslidernav ul a li {
height: 50px;
}
#vslidernav ul .active li {
}
.#vslidernav ul a:active {
background: transparent;
color: #9C9A99;
}
.vslider {
display: inline-block;
}
#vslidernav {
float: left;
width: 100px;
z-index: 1;
height: 250px;
}
#vsliderboxes {
position : relative;
overflow : hidden;
}
#vsliderboxes div {
height: 250px;
width: 900px;
}
#vsliderboxs-inner {
position : relative;
width : 900px;
height : 250px;
}
<div class="vslider">
<div id="vslidernav">
<ul>
<a id="1">
<li><img src="img/arrtop.gif"></li>
</a>
<a id="2">
<li><img src="img/arrdown.gif"></li>
</a>
<a id="3">
<li></li>
</a>
</ul>
</div>
<div id="vsliderboxes">
<div id="vsliderboxs-inner">
<div id="box1" class="active"><img src="img/slide1.gif"></div>
<div id="box2" class="inactive"><img src="img/slide2.gif"></div>
<div id="box3" class="inactive"><img src="img/slide3.gif"></div>
</div>
</div>
</div>
thanks for any advice
I think, that it isn't possible to solve this issue like you try to.
Because, when you work with the "top" property, you can't take one image from the top and append it to the other end because appending the image, will move the other images to another place --> the top property wouldn't be correct any more.
I think the contributed sliders (e.g. http://www.jssor.com/demos/vertical-slider.slider) work with the transform CSS property.
transform: translate3d()
Try to research about this property.
Roko C. Buljan answered on this page: loop carousel jquery
He uses a scrollTop loop for your problem.
I've also written a simple slider some time ago. I have now implemented the Roku C. Buljan method. Feel free to look at my code on Bitbucket.
https://bitbucket.org/d-stone/jqueryslider
An excerpt may help you:
value = prev_or_next == 'next' ? self.globals.slide_height : 0;
last = $('#container').find('> div:last');
first = $('#container').find('> div:first');
if(prev_or_next == 'prev') { // click on "next"-button
first.before(last); // put last element before first
settings.elements.inner.scrollTop(self.globals.slide_height); // set the scrollTop to 1 slide-height
}
// animation itself:
$('#container').stop().animate({scrollTop: value}, {
duration: settings.slide_speed,
done: function() {
if(prev_or_next == 'next') {
// put first item after last
last.after(first);
}
}
});
I'd advise you to validate your HTML (W3C Validator). There are some errors inside.
Invalid HTML can be the reason for some CSS and Javascript Errors.

How to create a side menu that the "active" item follow the page content location?

I'm looking to learn how to do this left menu :
http://js.devexpress.com/New/15_2/#HTML_5_JS_Core
When you scroll down the page, the "active" menu item change.
p.s.
Is there a name for this type of menu?
regards,
yaniv
Scroll Navigation
That is how we call these type of navigation bars. Basically you have to listen to the scroll event and calculate which element is in the viewport at the moment than you add a class to your navigation that marks the current menu element.
There is a nice demo built in jQuery but because jQuery is a thing of the past, I built one in Vanilla JS. See comments for explanations.
There are different ways to define which is the current element. In my Example it is the last one whose top line just passed the top line of the browser.
Working demo
window.onscroll = onScroll;
function onScroll() {
var removeActiveClass = function (elements) {
for (var i = 0; i < elements.length; ++i) {
elements[i].classList.remove('active');
}
}
var anchors = document.querySelectorAll('#menu-center a');
var previousRefElement = null;
for (var i = 0; i < anchors.length; ++i) {
// Get the current element by the id from the anchor's href.
var currentRefElement = document.getElementById(anchors[i].getAttribute('href').substring(1));
var currentRefElementTop = currentRefElement.getBoundingClientRect().top;
// Searching for the element whose top haven't left the top of the browser.
if (currentRefElementTop <= 0) {
//The browser's top line haven't reached the current element, so the previous element is the one we currently look at.
previousRefElement = anchors[i];
// Edge case for last element.
if (i == anchors.length - 1) {
removeActiveClass(anchors);
anchors[i].classList.add("active");
}
} else {
removeActiveClass(anchors);
previousRefElement.classList.add("active");
break;
}
}
}
body, html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
.menu {
width: 100%;
height: 75px;
position: fixed;
background-color:rgba(4, 180, 49, 0.6);
}
#menu-center {
width: 980px;
height: 75px;
margin: 0 auto;
}
#menu-center ul {
margin: 15px 0 0 0;
}
#menu-center ul li {
list-style: none;
margin: 0 30px 0 0;
display: inline;
}
.active {
font-size: 14px;
color: #fff;
text-decoration: none;
line-height: 50px;
}
a {
font-size: 14px;
color: black;
text-decoration: none;
line-height: 50px;
}
.content {
height: 100%;
width: 100%;
}
#portfolio {background-color: grey;}
#about {background-color: blue;}
#contact {background-color: red;}
<div class="menu">
<div id="menu-center">
<ul>
<li><a class="active" href="#home">Home</a></li>
<li>Portfolio</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
</div>
<div id="home" class="content"></div>
<div id="portfolio" class="content"></div>
<div id="about" class="content"></div>
<div id="contact" class="content"></div>
This is not exactly menu type, it is the way how you can position objects by html.
You can use position:Abosule property to achieve this effect:
http://www.w3schools.com/css/tryit.asp?filename=trycss_position_fixed
By this given divs are "flying" above the res of the page. In your case it could be a menu.
EDIT:
To sync this you need to detect when given anchor is currently seen.
It can be done by jQuery, this is sample draft of code, should explain clue of solution:
// list of header on page
var positions = [
$("#anchor1").offset().top,
$("#anchor2").offset().top,
$("#anchor3").offset().top,
];
var menu_objects= [
"#menu1",
"#menu2",
"#menu3"
];
var $w = $(window).scroll(function(){
// clear old
for(var v in menu_objects)
$(v).css({"color","white"});
for(var i=positions.length-1;i>=0;i--)
{
if(positions[i]>=$w.scrollTop())
{
$(menu_objects[i]).css({"color","red"});
break;
}
}
});

How to animate the list?

This is my JSFiddle
As you can see from the fiddle that there is a list that is being scrolled with the help of arrows.. So what I want is to animate that transition when the list visible and hidden.
I don't know about the animation. I have seen many examples and tried to adjust them with my example but it's not working... How do I get the list to animate?
$(document).ready(function(){
var code='';
for(var i=1;i<=20;i++)
{
code+="<li>list Item "+i+"</li>";
}
$('#list-items').html(code);
});
var list_items = [];
var index = 0;
var list_length = 0;
function getAllListItems() {
var temp = document.getElementsByTagName('li');
for (i = 0; i < temp.length; i++) {
list_items.push(temp[i]);
}
list_length = temp.length;
}
getAllListItems();
function move(dir) {
if (dir == left) {
list_items[index].style.display = 'block';
index--;
if (index < 0) {
index = 0;
}
} else if (dir == right) {
list_items[index].style.display = 'none';
if (index >= ((list_length) - 1)) {
index = (list_length) - 1;
} else {
index++;
}
} else {}
}
* {
box-sizing: border-box;
}
ul {
float:left;
height:50px;
width: 600px;
overflow: hidden;
}
ul li {
text-align: center;
border: 2px solid black;
width: 100px;
height: 50px;
float: left;
list-style-type: none;
background-color: aquamarine;
}
ul li:first-child {
display: block;
}
#left, #right {
float:left;
height:50px;
background-color:aqua;
font-size:2em;
padding-left: 20px;
padding-right:20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body onload='getAllListItems()'>
<div id='t'></div>
<button id='left' onClick="move(left)">
<</button>
<ul id='list-items'>
</ul>
<button id='right' onClick='move(right)'>></button>
</body>
You can easily just replace your lines:
list_items[index].style.display = 'block';
list_items[index].style.display = 'none';
with the jQuery show() and hide() functions:
$(list_items[index]).show("slow");
$(list_items[index]).hide("slow");
As demonstrated in my updated version of your Fiddle
For different transitions, you can use the animate() function, which lets you tell it what css properties to affect. In addition to numeric values, jQuery also supports the special values 'show', 'hide', and 'toggle' (which, incidentally, will show, hide, or toggle the show/hide status of an element using that property). So for instance, if you wanted to shrink them only horizontally and leave the vertical alone, you could change the .show() and .hide() calls to:
$(list_items[index]).animate({width:'show'}, 600);
$(list_items[index]).animate({width:'hide'}, 600);
I've demonstrated this in another updated Fiddle

Categories

Resources