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>
Related
I am currently making use of the following code which helps me in hiding and displaying the choices. But I am unable to hide and unselect them if choice 1 is unchecked.
var x= jQuery("#"+this.questionId+" input[choiceid=2]").closest("li").hide();
var y = jQuery("#"+this.questionId+" input[choiceid=3]").closest("li").hide();
this.questionclick = function(event, element) {
var selectedChoice = this.getSelectedChoices()
console.log(selectedChoice) //use this to get the value of the choice when you want the textbox to appear
if (selectedChoice == "1") {
x.show();
y.show();
alert(selectedChoice);
}
else if (selectedChoice == "2") {
//x.hide();
//y.hide();
alert(selectedChoice+"Else if");
}
else{
x.hide();
y.hide();
alert(selectedChoice+"Else ");
}
}
Some help would be greatly appreciated
Your question does not contain html that you are using. Here is a small demo I have created to demonstrate the grouped checkboxes and binding on click event with them. Play and do changes as per your need.
https://stackblitz.com/edit/grouped-checkboxes-binding-onclick-function
this keyword inside the function refers to the checkbox clicked. you can further checks as you do on normal html checkbox element. e.g this.checkedmeans document.getElementById("myCheck").checked to check if checkbox is checked or not.
HTML
<div class="question">
<h2 class="q-1">Click to write the Question text</h2>
</div>
<ul class="options-list" id="options-list">
<li>
<label>
<input type="checkbox" id="q1-opt1" name="q1['opt1']">
Click to write choice 1
</label>
</li>
<li>
<label>
<input type="checkbox" id="q1-opt2" name="q1['opt2']">
Click to write choice 2
</label>
</li>
<li>
<label>
<input type="checkbox" id="q1-opt3" name="q1['opt3']">
Click to write choice 3
</label>
</li>
<li>
<label>
<input type="checkbox" id="q1-opt4" name="q1['opt4']">
Click to write choice 4
</label>
</li>
</ul>
CSS
.options-list {
list-style-type: none;
margin: 0;
padding: 0;
}
.options-list li label {
display: block;
background: #ddd;
border-radius: 8px;
padding: 10px 20px;
margin: 0 0 10px;
cursor: pointer;
}
.options-list li label:hover {
background: #ccc;
}
.options-list li label > input {
display: none;
}
JS
(function() {
// get questions that you want to disable enable
var q1opt1 = document.getElementById("q1-opt2");
var q1opt2 = document.getElementById("q1-opt3");
// get list wrapping element of all checkboxes
var el = document.getElementById('options-list');
// get all checkboxes inside wrapping element
var options = el.getElementsByTagName('input');
// assign a function each checkbox on click
for( var i=0, len=options.length; i<len; i++ ) {
if ( options[i].type === 'checkbox' ) {
options[i].onclick = function(e) {
// if checkbox id is q1-opt1
// and is checked is checking if this is selected.
// checkbox is hidden with css
// play with the code
if ( this.id == 'q1-opt1' && this.checked ) {
q1opt1.parentElement.style.display = "none";
q1opt2.parentElement.style.display = "none";
} else {
q1opt1.parentElement.style.display = "block";
q1opt2.parentElement.style.display = "block";
}
}
}
}
})();
I have a simple function that is supposed to check if an element has a class. If it doesnt have the class, it should add the class. It should also iterate through all other elements in the series, and deselect them. So only 1 element should be shown at any time. I have looked at this, this, this and this as well as a bunch of others. I know the function should be simple, but I just cant resolve it.
const changeFilter = (itemNumber) => {
// grab element that has been clicked
let selector = document.getElementsByClassName(itemNumber);
// check if element doesnt has the class name that underlines it
if (!selector[0].classList.contains("darken-filter-selector")) {
// add the class if it doesnt have it
selector[0].classList.add("darken-filter-selector")
} else {
// iterate through all the elements, check if it has the class
// remove it if it doesnt have the class
for (let i = 0; i < 7 ; i++) {
if(i !== itemNumber) {
return selector[i].classList.contains("darken-filter-selector") ? selector[0].classList.remove("darken-filter-selector"):null
}
}
}
};
And it should not look like this (what is currently happening)
but rather should only allow for one selected element at a time...
The simplest way is to store the previous itemNumber into global variable like previousItemNumber.
Set the initial value of previousItemNumber to -1 (lower than 0) so that it can be used on changeFilter function.
And on changeFilter function, first, you check if previousItemNumber is existed or not (in other words, already selected item is existed or not when selecting new item) and if existed, remove the className there.
Add the className for the selected item and set the current itemNumber to previousItemNumber.
let previousItemNumber = -1;
const changeFilter = (itemNumber) => {
// grab element that has been clicked
let selector = document.getElementsByClassName(itemNumber);
if (previousItemNumber === itemNumber) {
return;
}
// Remove the class from previous selector
if (previousItemNumber >= 0) {
selector[previousItemNumber].classList.remove("darken-filter-selector");
}
selector[itemNumber].classList.add("darken-filter-selector");
previousItemNumber = itemNumber;
};
You can achieve the desired using input type="checkbox" and a bit of JS:
const EL_checkboxesOne = document.querySelectorAll(".checkboxesOne");
const checkboxesOne = (EL_group) => {
const inputs = EL_group.querySelectorAll('[type="checkbox"]');
EL_group.addEventListener("input", (ev) => {
[...inputs].filter(EL => EL !== ev.target).forEach(EL => EL.checked = false);
});
};
EL_checkboxesOne.forEach(checkboxesOne);
.checkboxesOne {
display: flex;
font: bold 16px/1.4 sans-serif;
color: #666;
}
.checkboxesOne input {
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
clip: rect(0 0 0 0);
clip-path: inset(100%);
}
.checkboxesOne span {
padding: 10px 0;
margin: 0 10px;
user-select: none;
cursor: pointer;
}
.checkboxesOne input:checked + span {
box-shadow: 0 4px green;
}
<div class="checkboxesOne">
<label><input type="checkbox" name="filter" value="all"><span>ALL</span></label>
<label><input type="checkbox" name="filter" value="new"><span>NEW</span></label>
<label><input type="checkbox" name="filter" value="wip"><span>WIP</span></label>
<label><input type="checkbox" name="filter" value="hot"><span>HOT</span></label>
<label><input type="checkbox" name="filter" value="won"><span>WON</span></label>
<label><input type="checkbox" name="filter" value="lost"><span>LOST</span></label>
<label><input type="checkbox" name="filter" value="dnc"><span>DNC</span></label>
</div>
I went with this function, as I thought it was the easiest and required the least modification from my original function
const changeFilter = (itemNumber) => {
// grab element that has been clicked
let selector = document.getElementsByClassName(itemNumber);
// check if element doesnt has the class name that underlines it
if (!selector[0].classList.contains("darken-filter-selector")) {
// add the class if it doesnt have it
selector[0].classList.add("darken-filter-selector");
}
// iterate through all the elements, check if it has the class
// remove it if it doesnt have the class
for (let i = 0; i < 7; i++) {
if (i !== itemNumber) {
let otherEls = document.getElementsByClassName(i);
if (otherEls[0].classList.contains("darken-filter-selector")) {
otherEls[0].classList.remove("darken-filter-selector");
}
}
}
};
This is my suggestion. It uses Event Delegation. Change the style as you like.
options.onclick = function(e) {
if (e.target.tagName != "LI") return;
var selected = options.querySelector(".active");
if (selected) {
selected.removeAttribute("class");
}
e.target.setAttribute("class", "active");
console.log(e.target.dataset.option);
};
#options {
display: flex;
justify-content: center;
}
#options li {
margin: 0 10px 0 10px;
padding: 10px;
cursor: pointer;
list-style: none;
}
#options li.active {
background-color: green;
pointer-events: none;
border-radius: 5px;
}
<ul id="options">
<li data-option="all">ALL</li>
<li data-option="new">NEW</li>
<li data-option="wip">WIP</li>
<li data-option="hot">HOT</li>
<li data-option="won">WON</li>
<li data-option="lost">LOST</li>
<li data-option="dnc">DNC</li>
</ul>
You can also do without using Data Attribute (data-option="..."): just use e.target.innerHTML.
[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>
Note: I can't use jQuery, only vanilla javascript
I'm not really fluent in pure JS. And this time I can't use any external resources (like jquery).
What I need:
If div1 class is active, hide text2
If div2 class is active, hide text1
I made it somehow to work, but my JS doesn't trigger when the class changes dynamic with another javascript code.
Code that triggers the active class
function activeClass(elem) {
var a = document.getElementsByClassName('item')
for (i = 0; i < a.length; i++) {
a[i].classList.remove('active')
}
elem.classList.add('active');
}
Code that should trigger hide/show when the class changes
if (document.querySelector(".text2").classList.contains("active")) {
document.getElementsByClassName('text1s')[0].style.visibility = 'hidden';
document.getElementsByClassName('text2s')[0].style.visibility = 'visible';
}
if (document.querySelector(".text1").classList.contains("active")) {
document.getElementsByClassName('text2s')[0].style.visibility = 'hidden';
document.getElementsByClassName('text1s')[0].style.visibility = 'visible';
}
What did I do wrong?
Codepen demo
Place your conditions inside click handler.
Add inline visibility style for inactive element
function activeClass(elem) {
var a = document.getElementsByClassName('item')
for (i = 0; i < a.length; i++) {
a[i].classList.remove('active')
}
elem.classList.add('active');
if (document.querySelector(".text2").classList.contains("active")) {
document.getElementsByClassName('text1s')[0].style.visibility = 'hidden';
document.getElementsByClassName('text2s')[0].style.visibility = 'visible';
}
if (document.querySelector(".text1").classList.contains("active")) {
document.getElementsByClassName('text2s')[0].style.visibility = 'hidden';
document.getElementsByClassName('text1s')[0].style.visibility = 'visible';
}
}
body {
margin: 3em;
}
.item {
cursor: pointer;
}
a {
padding: 10px;
}
.active {
color: red;
border: 1px solid red;
}
<a class="item text1" onclick="activeClass(this)">show text</a>
<a class="item text2 active" onclick="activeClass(this)">hide text</a>
<br>
<br>
<h1 class="text1s" style='visibility:hidden;'>TEXT 1</h1>
<h1 class="text2s">TEXT 2</h1>
Updated Codepen
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()">