creating a rolling menu: rolling just once - javascript

[EDIT]
I rebuild my code after numbtongue hint. It looks totally different now, and is working pretty well. Except that it is working once only ! After one roll, it doesn't roll anymore...
I have two functions : one for transitions and the other one for replacing content. In the 'transition' function, I chose to add classes to the element to transit, and add some CSS for these classes.
When I run my code, it seems that everything goes perfectly all the time, except that the transitions don't happen. What's wrong ??
JSFIDDLE : jsfiddle.net/arnaudambro/ode8bowb/2/
[ORIGINAL]
I am trying to create a "rolling menu", looking quite like the one from this awwwarded website : north-east-venture.com on the right side of the page (no advertising from me at all, just for you to know what I am refering too, for a better understanding of the issue I am confronted with).
What I am looking for is: when someone click on one item of the menu, this item goes directly up, and the items which were above would go under the stack.
I made something up which is quite working here :
JS Fiddle : jsfiddle.net/arnaudambro/7s6ncxyp/
But as you can see, there are no transitions.
Here is the code showing the "working" transition :
JSFiddle : jsfiddle.net/arnaudambro/xtrvsgor/
To make the transitions working, I had to comment the lines 84, 153, 172 and 174 in the JS.
I tried everything I could to make the transitions working in the whole menu, but it seems that when I "populate the new menu", every transition is killed.
What i wrong with my code ?

Hint: clicking on links loses menu position (sets it to array size currently = 5), instead should be cycling trough (see attached) for other links..

Success !
With some timeouts, I did the trick. Unfortunately, it is working but still a bit jerky, because it seems there is no other choice with timeouts. I tried to measure time spent to repopulateMenu to do its job, and put it as a setTimeout value, but it didn't work, the time was too short.
Anyway, it's quite working already, nice !
/*------------------------------ Variables -----------------------------------*/
const menu = document.querySelector('.menu');
const items = [...document.querySelectorAll('.item')];
const itemsLink = [...document.querySelectorAll('.item-link')];
const itemsContent = [...document.querySelectorAll('.item-content')];
let translateYHeight = itemsLink[0].offsetHeight;
console.log(translateYHeight)
let textContentItemAtTheTopOfTheStack;
let transitionInSeconds;
let transitionInMilliSeconds;
let clickedItemIndex;
/*--------------------------- Functions - callbacks --------------------------*/
//Get the index. Called in the STEP 1.
function getTheIndexOfTheClickedItem(e) {
//Variable
let clicked;
//We select the <p> only
if (e.target.tagName == "LI") {
clicked = e.target.firstElementChild.firstElementChild;
} else if (e.target.tagName == "A") {
clicked = e.target.firstElementChild;
} else if (e.target.tagName == "P") {
clicked = e.target;
} else {
return false;
}
//Nothing happen if we clicked on the first item
if (clickedItemIndex === 0) {
return;
}
//We get the index of the clicked item
clickedItemIndex = items.indexOf(clicked.parentElement.parentElement);
//We get the textContent of the clicked item, so that when the textContent
//of the first item in the menu is the proper textContent, we are done
textContentItemAtTheTopOfTheStack = itemsContent[clickedItemIndex].textContent;
//We set the total transition time to 1 second
transitionInSeconds = 1 / clickedItemIndex;
transitionInMilliSeconds = transitionInSeconds * 1000;
translateAndFade();
}
/*--------------------------- STEP 1 --------------------------*/
function translateAndFade() {
//We put the proper transition depending on when the translateAndFade function
//is called
let transitionStyle;
if (clickedItemIndex === 1) {
transitionStyle = 'ease-in-out';
} else if (itemsLink[1].textContent.trim() === textContentItemAtTheTopOfTheStack) {
transitionStyle = 'ease-out';
} else if (itemsLink[clickedItemIndex].textContent.trim() === textContentItemAtTheTopOfTheStack) {
transitionStyle = 'ease-in';
} else {
transitionStyle = 'linear';
}
//We add the transitions and fadings we want
itemsLink.forEach(link => {
if (itemsLink.indexOf(link) === 0) {
//We add the fade-out for the first menu-item
link.style.opacity = 0;
link.style.transform = `translateY(-${translateYHeight}px)`;
link.style.transition = `all ${transitionInSeconds}s ${transitionStyle}`;
} else if (itemsLink.indexOf(link) === (itemsLink.length - 1)) {
//We add the fade-in for the last menu-item
link.firstElementChild.textContent = itemsLink[0].textContent.trim();
link.style.opacity = 1;
link.style.transform = `translateY(-${translateYHeight}px)`;
link.style.transition = `all ${transitionInSeconds}s ${transitionStyle}`;
} else {
//We translate every menu-item one step up
link.style.transform = `translateY(-${translateYHeight}px)`;
link.style.transition = `all ${transitionInSeconds}s ${transitionStyle}`;
}
});
//We call repopulateMenu, to repopulate the menu, with enough timeout to
//let the transition happening
window.setTimeout(repopulateMenu, transitionInMilliSeconds);
}
/*--------------------------- STEP 2 --------------------------*/
function repopulateMenu() {
//We remove the transitions
itemsLink.forEach(link => {
if (itemsLink.indexOf(link) === 0) {
//We remove the fade-out for the first menu-item
link.style.opacity = 1;
link.style.transform = ``;
link.style.transition = ``;
} else if (itemsLink.indexOf(link) === (itemsLink.length - 1)) {
//We remove the fade-in for the last menu-item
link.style.opacity = 0;
link.style.transform = ``;
link.style.transition = ``;
} else {
//We remove the translation of all of them
link.style.transform = ``;
link.style.transition = ``;
}
});
//We update the textContents
itemsContent.forEach(item => {
// We put back emptiness for the last menu-item
if (itemsContent.indexOf(item) === (itemsContent.length - 1)) {
item.textContent = '';
} else {
//We replace the content of the item by the one below it
item.textContent = itemsContent[itemsContent.indexOf(item) + 1].textContent.trim();
}
});
//We do all again until the proper item-menu is on top of the stack.
if (itemsContent[0].textContent != textContentItemAtTheTopOfTheStack) {
window.setTimeout(translateAndFade, 20);
} else {
return;
}
}
/*--------------------------- Event listeners --------------------------------*/
menu.addEventListener('click', getTheIndexOfTheClickedItem);
html,
body {
font-family: sans-serif;
font-weight: 100;
color: rgba(41, 44, 45, 1.00);
}
.menu {
margin-top: 50px;
margin-left: 50px;
list-style: none;
/*border: 1px solid #000;*/
}
.transition-translateY {
transition: all 1s;
transform: translateY(-44px);
}
.transition-fadeIn {
transition: all 1s;
transform: translateY(-44px);
opacity: 1;
}
.transition-fadeOut {
transition: all 1s;
transform: translateY(-44px);
opacity: 0;
}
.item {
padding-top: 2px;
padding-bottom: 2px;
font-size: 0.75em;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
text-align: left;
/*border: 1px solid #000;*/
}
.item-link,
.item-link:hover {
height: 25px;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
text-decoration: none;
color: inherit;
}
<body>
<ul class="menu">
<li class="item">
<a href="#" class="item-link">
<p class="item-content" data-menu-position="0">Item 1</p>
</a>
</li>
<li class="item">
<a href="#" class="item-link">
<p class="item-content" data-menu-position="1">Item 2</p>
</a>
</li>
<li class="item">
<a href="#" class="item-link">
<p class="item-content" data-menu-position="2">Item 3</p>
</a>
</li>
<li class="item">
<a href="#" class="item-link">
<p class="item-content" data-menu-position="3">Item 4</p>
</a>
</li>
<li class="item">
<a href="#" class="item-link">
<p class="item-content" data-menu-position="4">Item 5</p>
</a>
</li>
<li class="item">
<a href="#" class="item-link" style="opacity:0">
<p class="item-content" data-menu-position="5"></p>
</a>
</li>
</ul>
</body>

Related

Toggling Functions With Event-listeners

I'm currently working on a font size changer for a website and it "works" but is not user-friendly. Right now I have it set up to on click remove the event listeners from the other id's (smBtn On, mdBtn Gone, lgBtn Gone) and return them when none is pressed. Where in actuality, I want it when upon button press it just turns the others off. So I guess my question is how do I toggle my functions
My Idea: One Button is ON forces the other two OFF, when clicked off forces all off Example (Med ON, Sm OFF Lg OFF) (Sm ON, Med OFF, Lg ON) (All OFF)
//Countp and Findp are used in a loop to find all the P tags on a page and then give them the class size
var countP = document.getElementsByTagName('P')
var i;
for (i = 0; i < countP.length; i++) {
var findP = document.getElementsByTagName('P')[i];
findP.setAttribute('class', 'size');
}
//these are all the buttons used to active the functions
document.getElementById("smBtn").addEventListener("click", smallTxt);
document.getElementById("mdBtn").addEventListener("click", mediumTxt);
document.getElementById("lgBtn").addEventListener("click", largeTxt);
//All the functions use the same code just changed Id's and class names that match the small,med,large
function smallTxt() {
// finds all P tags with the Class name Size and then adds the css small
var smButton = document.getElementById("smBtn");
for (i = 0; i < countP.length; i++) {
var smWords = document.getElementsByClassName("size");
[i];
smWords[i].classList.toggle("small");
}
//toggles the css only
smButton.classList.toggle("clicked");
//this is to prevent the other sizes from being clicked by removing the function and when not in use add the functions back
if (smButton.className == "clicked") {
document.getElementById("mdBtn").removeEventListener("click", mediumTxt);
document.getElementById("lgBtn").removeEventListener("click", largeTxt);
} else {
document.getElementById("mdBtn").addEventListener("click", mediumTxt);
document.getElementById("lgBtn").addEventListener("click", largeTxt);
}
}
function mediumTxt() {
var medButton = document.getElementById("mdBtn");
for (i = 0; i < countP.length; i++) {
var medWords = document.getElementsByClassName("size");
[i];
medWords[i].classList.toggle("medium");
}
medButton.classList.toggle("clicked");
if (medButton.className == "clicked") {
document.getElementById("smBtn").removeEventListener("click", smallTxt);
document.getElementById("lgBtn").removeEventListener("click", largeTxt);
} else {
document.getElementById("smBtn").addEventListener("click", smallTxt);
document.getElementById("lgBtn").addEventListener("click", largeTxt);
}
}
function largeTxt() {
var lgButton = document.getElementById("lgBtn");
for (i = 0; i < countP.length; i++) {
var lgWords = document.getElementsByClassName("size");
[i];
lgWords[i].classList.toggle("large");
}
lgButton.classList.toggle("clicked");
if (lgButton.className == "clicked") {
document.getElementById("mdBtn").removeEventListener("click", mediumTxt);
document.getElementById("smBtn").removeEventListener("click", smallTxt);
} else {
document.getElementById("mdBtn").addEventListener("click", mediumTxt);
document.getElementById("smBtn").addEventListener("click", smallTxt);
}
}
.small {
font-size: 10px;
}
.medium {
font-size: 20px;
}
.large {
font-size: 30px;
}
.clicked {
color: #012169;
text-shadow: 2px 2px 4px #000000;
}
ul li {
display: inline-block;
}
<h2>Font Text Changer V2</h2>
<p>Click on one of the a's next to font size to change the size of the text, only one A can be active at a time their for must turn it off to use other sizes</p>
<p>Developer Idea:One Button is ON forces the other two OFF, when clicked off forces all off Example (Med ON, Sm OFF Lg OFF) (Sm ON, Med OFF, Lg ON) (All OFF) </p>
<p> Beneath is how you test the the function</p>
<ul>
<li style="font-size:14px">Font size:</li>
<li id="smBtn" style="font-size:13px">A</li>
<li id="mdBtn" style="font-size:17px">A</li>
<li id="lgBtn" style="font-size:20px">A</li>
</ul>
An easier way would be to change the font-size of the html tag by adding classes with javascript. Then all child elements will follow. I.E.:
html {
font-size: 100%; //16px
}
html.small {
font-size: 75% //12px
}
html.big {
font-size: 125% //20px
}
I would delegate
document.querySelectorAll('P').forEach(p => p.setAttribute('class', 'size'));
document.getElementById("fontList").addEventListener("click", function(e) {
const tgt = e.target.closest(".btn");
if (tgt) {
let clicked = this.querySelector(".clicked")
if (clicked && clicked != tgt) return; // you need to click again
tgt.classList.toggle("clicked"); // toggle on and off
clicked = this.querySelector(".clicked"); // find the one clicked
document.querySelectorAll(".size").forEach(p => {
if (clicked) p.classList.toggle(clicked.dataset.size); // add or remove
else p.className = "size"; // remove all
})
}
})
.small {
font-size: 10px;
}
.medium {
font-size: 20px;
}
.large {
font-size: 30px;
}
.clicked {
color: #012169;
text-shadow: 2px 2px 4px #000000;
}
ul li {
display: inline-block;
}
<h2>Font Text Changer V2</h2>
<p>Click on one of the a's next to font size to change the size of the text, only one A can be active at a time their for must turn it off to use other sizes</p>
<p>Developer Idea:One Button is ON forces the other two OFF, when clicked off forces all off Example (Med ON, Sm OFF Lg OFF) (Sm ON, Med OFF, Lg ON) (All OFF) </p>
<p> Beneath is how you test the the function</p>
<ul id="fontList">
<li style="font-size:14px">Font size:</li>
<li class="btn" data-size="small" style="font-size:13px">A</li>
<li class="btn" data-size="medium" style="font-size:17px">A</li>
<li class="btn" data-size="large" style="font-size:20px">A</li>
</ul>
Selecting fonts from li elements is not ideal but in this particular setup one way of doing the job could be;
var choices = document.querySelectorAll("li:nth-child(n+2)"),
context = document.querySelectorAll("p");
choices.forEach(choice => choice.addEventListener("click", e => context.forEach(p => p.style.fontSize = e.target.style.fontSize)));
<h2>Font Text Changer V2</h2>
<p>Click on one of the a's next to font size to change the size of the text, only one A can be active at a time their for must turn it off to use other sizes</p>
<p>Developer Idea:One Button is ON forces the other two OFF, when clicked off forces all off Example (Med ON, Sm OFF Lg OFF) (Sm ON, Med OFF, Lg ON) (All OFF) </p>
<p> Beneath is how you test the the function</p>
<ul>
<li style="font-size:14px">Font size:</li>
<li id="smBtn" style="font-size:13px">A</li>
<li id="mdBtn" style="font-size:17px">A</li>
<li id="lgBtn" style="font-size:20px">A</li>
</ul>

I need to animate the change the 3 letters with the items of an array with JavaScript

I need to animate the change of these 3 characters with the data of the array, when I click this blue button on the right.
This is the HTML code I have written so far.
<div class="cards">
<div id="card1" class="card">L</div>
<div id="card2" class="card">A</div>
<div id="card3" class="card">X</div>
<a class="btn btn-flat shuffle" href="#" onclick="travelSurprise();">
</a>
</div>
Javascript code is here.
function travelSurprise() {
let cities = ["NYC", "PTH", "SDN", "KTY", "PRT"];
let card1 = document.getElementById("card1");
let card2 = document.getElementById("card2");
let card3 = document.getElementById("card3");
for (let i = 0; i < cities.length; i++) {
setInterval(function shuffle() {
card1.innerHTML = cities[i].charAt(0);
card2.innerHTML = cities[i].charAt(1);
card3.innerHTML = cities[i].charAt(2);
}, 500);
}
}
I need to change these three letters when I click the button. Animation should be like the 3 letters will change to all the elements of the array for 3,4 seconds and stop at a random position.
Try using setTimeout() instead, where the second argument is the 500ms time multiplied by an index of every array item. For the shuffle, use Fisher-Yates algorithm as described here and just do it every time the a is clicked.
function shuffle(array) {
// shuffle your array code
return array;
}
function travelSurprise(event) {
let cities = ["NYC", "PTH", "SDN", "KTY", "PRT"];
let card1 = document.getElementById("card1");
let card2 = document.getElementById("card2");
let card3 = document.getElementById("card3");
shuffle(cities);
cities.forEach((city, index) => {
setTimeout(() => {
card1.innerHTML = city.charAt(0);
card1.innerHTML = city.charAt(1);
card2.innerHTML = city.charAt(2);
}, (index * 500));
});
}
.cards > div {
display: inline-block;
padding: 2rem;
background: lightblue;
border-radius: .3rem;
}
a {
display: inline-block;
background: #f2f2f2;
width: 1rem;
height: 1rem;
}
<div class="cards">
<div id="card1" class="card">L</div>
<div id="card2" class="card">A</div>
<div id="card3" class="card">X</div>
<a class="btn btn-flat shuffle" href="#" onclick="travelSurprise();">
</a>
</div>

Change Background color of Active list item in bootstrap

I have item group list
<div id="MainMenu">
<div class="list-group panel">
Menu 1
<div class="collapse" id="why">
Menu 1 a
Menu 1 b
Menu 1 c
Menu 1 d
Menu 1 e
Menu 1 f
</div>
Menu 2
<div class="collapse" id="joinus">
Menu 2 a
Menu 2 b
Menu 2 c
Menu 2 d
Menu 2 e
</div>
</div>
</div>
I want to change background of active list item, I Know how to change background, but I am unable to get which list is active, or inactive by JavaScript, tried lots of solution given on others but didn't woJrk.
JsFiddle
UPDATE:
Don't know why bootstrap isn't doing it, but here's some jQuery on a fiddle for you. The alert is displaying the href that is active.
Is that what you're after?
Update - 09/01/2022
Edited the old fiddle, here's the new one http://jsfiddle.net/dh7t3cbp/1/
$('.list-group').on('click', '> a', function(e) {
var $this = $(this);
$('.list-group').find('.active').removeClass('active');
$this.addClass('active');
alert($this.attr('href') + ' is active');
});
$('.list-group .collapse').on('click', '> a', function(e) {
var $this = $(this),
$parent = $this.parent('.collapse');
$parent.find('.active').removeClass('active');
$this.addClass('active');
alert($this.attr('href') + ' is active');
});
.list-group panel.active, .list-group panel.active a.active {
background-color: #030;
border-color: #aed248;
}
Add the following css in your code as :
.list-group-item[aria-expanded="true"]{
background-color: black !important;
border-color: #aed248;
}
Demo
What i does it assign and id to every link in list that is also the page name, and made a js function that is called on body load of the page. the function get the current file name from url and determines which page is this, then by js i made that link class active. this solve my problem. however i share this solution for others to improvement.
function get_current_page() {
var pathArray = window.location.pathname.split("/");
var current_page = pathArray[pathArray.length - 1];
current_page_array = current_page.split(".");
current_page = current_page_array[0];
if (
current_page == "students" ||
current_page == "my-profile" ||
current_page == "faqs" ||
current_page == "forecast-career"
) {
document.getElementById("joinuslist").className += " active";
document.getElementById("joinus").className += " in";
if (current_page == "students") {
document.getElementById("students").className += " active";
} else if (current_page == "faqs") {
document.getElementById("faqs").className += " active";
} else if (current_page == "forecast-career") {
document.getElementById("forecast-career").className += " active";
} else if (current_page == "my-profile") {
document.getElementById("my-profile").className += " active";
} else {
}
} else if (
current_page == "values" ||
current_page == "ambassadors" ||
current_page == "documentary"
) {
if (current_page == "values") {
document.getElementById("values").className += " active";
} else if (current_page == "ambassadors") {
document.getElementById("ambassadors").className += " active";
} else if (current_page == "documentary") {
document.getElementById("documentary").className += " active";
} else {
}
}
}
.list-group-item.active:hover {
background-color: #aed248 !important;
border-color: #aed248 !important;
}
.list-group-item.active,
.list-group-item.active:hover {
background-color: #007715 !important;
border-color: #aed248 !important;
}
#joinus .list-group-item.active,
.list-group-item.active:hover {
background-color: #adce1b !important;
border-color: #adce1b !important;
}
#whyptcl .list-group-item.active,
.list-group-item.active:hover {
background-color: #adce1b !important;
border-color: #adce1b !important;
}
.panel {
margin-bottom: 20px;
background-color: transparent !important;
border: 0px solid transparent;
border-radius: 5px;
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
}
<body onload="get_current_page()">
<div id="MainMenu">
<div class="list-group panel">
<a
id="whylist"
href="#why"
class="list-group-item"
data-toggle="collapse"
data-parent="#MainMenu"
>Menu 1</a
>
<div class="collapse" id="why">
<a
id="values"
href="values.html"
onclick="activate(this)"
class="list-group-item"
data-toggle="collapse"
data-parent="#SubMenu1"
>Menu 1 a</a
>
<a
id="ambassadors"
href="ambassadors.html"
onclick="activate(this)"
class="list-group-item"
>Menu 1 b</a
>
<a
id="documentary"
href="documentary.html"
onclick="activate(this)"
class="list-group-item"
>Menu 1 c</a
>
</div>
<a
id="joinuslist"
href="#joinus"
class="list-group-item"
data-toggle="collapse"
data-parent="#MainMenu"
>Menu 2</a
>
<div class="collapse" id="joinus">
<a
id="my-profile"
href="my-profile.html"
onclick="activate(this)"
class="list-group-item"
>Menu 2 a</a
>
<a
id="students"
href="students.html"
onclick="activate(this)"
class="list-group-item"
>Menu 2 b</a
>
<a
id="forecast-career"
href="forecast-career.html"
onclick="activate(this)"
class="list-group-item"
>Menu 2 c</a
>
<a
id="faqs"
href="faqs.html"
onclick="activate(this)"
class="list-group-item"
>Menu 2 e</a
>
</div>
</div>
</div>
</body>
The solution is simple but maybe not obvious.
You can pass this (the clicked element) to an onclick event handler and then set the active class on the selected menu.
var activate = function(el) {
var current = document.querySelector('.active');
if (current) {
current.classList.remove('active');
}
el.classList.add('active');
}
I created this Fiddle to answer your question
http://jsfiddle.net/Ltp9qLox/9/
The script can be greatly improved, this is just an example. I'm not aware of any non-JS way to achieve the same result.
You can also store the old activated element so you don't have to use query selector every time, in this way the script would be
var current;
var activate = function(el) {
if (current) {
current.classList.remove('active');
}
current = el;
el.classList.add('active');
}
Bu then you have to initialize currentwith the value of the starting element.
Adding Persistency
Of course any change to the style of an element can't survive after a refresh without implementing some kind of persistency that is something completely different than the simple implementation. Keep in mind that there are hundreds of different ways to achieve this, one of which is NOT refreshing at all the page.
Anyway if you prefer the quick and dirt way then using localStorage is probably the best solution. This is a simple implementation
var currentHref = localStorage.getItem("currentSelected");
var current = currentHref ? document.querySelector('[href="'+currentHref+'"]') : null;
function activate(el) {
if (current && current !== el) {
current.classList.remove('active');
}
current = el;
current.classList.add('active');
localStorage.setItem("currentSelected", current.getAttribute('href'));
}
Basically you save something that you can use to recognize the element that was selected, in this case i used the href attribute value because in our case that is unique, but you could also assign id or other attributes to the elements and use that.
Then on load i read the localStorage to retrieve the saved href and if found i get the element inside the page using a simple querySelector.
Just remember that copy-pasting this kind of solution doesnt help you building better websites, you should read articles on the internet and implement what solution is best for your own use case.
Just to change the active item background color, (I've changed to grey from default - blue) add this to your css:
.list-group-item.active {
background-color: grey;
border-color: grey; }
You can add these Bootstrap classes;
.list-group-item-dark
.list-group-item-success
.list-group-item-warning
.list-group-item-primary
.list-group-item-danger
.list-group-item-secondary
.list-group-item-info

Return id on next "page" in single page site based on current page id using javascript

I am creating a simple website which should have multiple pages showing a different background and main text, but with the same logo and menu. The next page should slide in from the right when a button is pressed and selecting a page from the menu should transition directly to that page. I have decided to make this a single page site to make use of CSS3 transitions. Example code for the next button (minus transitions) is here: http://jsfiddle.net/xoa029jz/1/
I am currently working out which background and text to display using the following javascript:
function getNextPage(pageid) {
if (pageid == "page-1") {
return $('#page-2');
} else if (pageid == "page-2") {
return $('#page-3');
} else if (pageid == "page-3") {
return $('#page-1');
}
}
The site will have 7 pages, so this seems cumbersome. Is there a better way of using sequential ids in javascript?
The site will only have one image and one sentence per "page", so I don't think it is necessary to use Ajax, but I am willing to be corrected on this.
You can use class in this case which will not bound you for any number of pages,
function getNextPage(pageid) {
if($('.current-page').next('.page-text').length){
return $('.current-page').next('.page-text');
}
return $('.page-text:first');
}
function slideToNext() {
var currentPage = $('.current-page');
var nextPage = getNextPage(currentPage.attr('id'));
$(currentPage).removeClass('current-page');
$(nextPage).addClass('current-page');
var currentBackground = getCurrentBackground();
var nextBackground = getNextBackground(currentBackground);
$('#bg').removeClass(currentBackground);
$('#bg').addClass(nextBackground);
}
function getNextPage(pageid) {
if($('.current-page').next('.page-text').length){
return $('.current-page').next('.page-text');
}
return $('.page-text:first');
}
function getCurrentBackground() {
var bg = $('#bg');
if (bg.hasClass('bg-1')) {
return "bg-1";
} else if (bg.hasClass('bg-2')) {
return "bg-2";
} else if (bg.hasClass('bg-3')) {
return "bg-3";
}
}
function getNextBackground(bg) {
if (bg == "bg-1") {
return "bg-2";
} else if (bg == "bg-2") {
return "bg-3";
} else if (bg == "bg-3") {
return "bg-1";
}
}
.page {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background-size: cover;
background-position: center center;
z-index:1;
}
.page-text {
margin-top: 71px;
display: none;
}
.current-page {
display: inline;
visibility: visible;
}
.bg-1 {
background-color:#D8F6CE;
}
.bg-2 {
background-color:#CEECF5;
}
.bg-3 {
background-color:#E2A9F3;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<body class="page bg-1" id="bg">
<div id="page">
<img id="logo" src="images/logo.png" width="295" height="92" />
<div id="menu">
<ul>
<li>
<button>Page 1</button>
</li>
<li>
<button>Page 2</button>
</li>
<li>
<button>Page 3</button>
</li>
</ul>
</div>
<div class="page-text current-page" id="page1">Page 1 text</div>
<div class="page-text" id="page2">Page 2 text</div>
<div class="page-text" id="page3">Page 3 text</div>
<button type="button" onclick="slideToNext()">Next</button>
</div>
</body>
Yes. Get the ID as a number, and increment it:
var num = +pageid[5];
if (num < 7) {
return $('#page-'+(num+1));
}
return $('#page-1');
If there is only 7 pages, cant u loop it, like:
for(var i=0;i<=7;i++){
if (pageid == "page-"+i) {
return $('#page-'+i);
}
}
Change your code to this
//just remove the word page so that only the number will left (e.g. "page"1 )
var nextPage = getNextPage(currentPage.attr('id').replace('page', ''));
Then your function will be shorter and no element count hard coding.
function getNextPage(pageid) {
return $('#page' + (pageid + 1)); //just take care the logic for returning to first page
}

Changing the colour of a logo while scrolling

Currently, I have setup a page that when scrolling down, the colour of the menu changes to make up for the backgrounds - so on the white background the text would be black and vice versa.
I would like to change the text to a logo so that on the white background the logo would be black; using the image LOGOBLACK.png and vice versa with LOGOWHITE.png.
Here is the menu in index.html:
<nav id="menu" class="hidden">
<ul>
<li class="go-home">
<img src="images/LOGOBLACK.png">
</li>
</ul>
Here is the javascript code that I was using before:
function updateMenuColor() {
var t = Math.max(window.scrollY, 0) + 50,
e = t - y;
setScrollUp(0 >= e), y = t;
for (var i = document.getElementsByTagName("section"), n = document.body.getBoundingClientRect(), s = 0; s < i.length; s++) {
var a = i[s],
o = a.getBoundingClientRect(),
r = o.top - n.top,
l = o.bottom - n.top;
if (y > r && l > y) {
var c = a.classList.contains("white");
c && !$menuIsWhite ? (switchMenuToWhite(), $menuIsWhite = !0) : !c && $menuIsWhite && (switchMenuToBlack(), $menuIsWhite = !1);
var h = a.classList.contains("text");
h && !$menuIsFaded ? (fadeMenuIn(), $menuIsFaded = !0) : !h && $menuIsFaded && (fadeMenuOut(), $menuIsFaded = !1)
}
}
}
function switchMenuToWhite() {
document.body.classList.add("white")
}
function switchMenuToBlack() {
document.body.classList.remove("white")
}
What I am failing to understand is how to substitute the text for a logo. Any type of comment is always appreciated.
Thanks for the help in advance!
The previous solution worked by adding and removing a class on body. There is no pure css solution to changing the src-attribute of the logo, unless you want to have two img tags and toggle between the two. This solution just finds the img-tag we want to change, and changes it src attribute to the new url:
document.getElementsByClassName("go-home")[0].getElementsByTagName('img')[0].src = "/images/LOGOWHITE.png";
An alternate solution is to have two img-tags, one for each version, and toggle them. You can keep your current javascript code, but need to add the following css, and change the html a bit:
/* Hide white logo on white background */
body.white .logowhite {
display: none;
}
/* Hide black logo on non-white (black) background */
body:not(.white) .logoblack {
display: none;
}
<a href="index.html">
<img class="logoblack" src="images/LOGOBLACK.png">
<img class="logowhite" src="images/LOGOWHITE.png">
</a>
function togglewhite() {
if (document.body.classList.contains("white")) {
console.log("a");
document.body.classList.remove("white");
} else {
console.log("b");
document.body.classList.add("white");
}
}
/* This is not necessary; it is just for easier viewing what happens */
img {
width: 100px;
height: 100px;
}
.logoblack {
background: black;
}
.logowhite {
background: gray;
}
/* This is necessary */
/* Hide white logo on white background */
body.white .logowhite {
display: none;
}
/* Hide black logo on non-white (black) background */
body:not(.white) .logoblack {
display: none;
}
<nav id="menu" class="hidden">
<ul>
<li class="go-home">
<a href="index.html">
<img class="logoblack" src="images/LOGOBLACK.png">
<img class="logowhite" src="images/LOGOWHITE.png">
</a>
</li>
</ul>
</nav>
<input type="button" value="Toggle white" onclick="togglewhite()">

Categories

Resources