Changing the colour of a logo while scrolling - javascript

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()">

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>

How to get JS tab selector to not scroll

I'm using this JS for tabs. However, it continually makes the selected tab box scroll to the top of the page when clicked.
I can't figure out what part of it is doing that and am trying to get rid of it. Essentially I just want it to function as a normal tab clicker without causing the entire page to scroll.
Any help?
I added a snippet with a large top margin so you can see what happens when you click the tab. I just want those boxes to change without the page physically scrolling to them on its own.
'use strict';
function Tabs() {
var bindAll = function() {
var menuElements = document.querySelectorAll('[data-tab]');
for (var i = 0; i < menuElements.length; i++) {
menuElements[i].addEventListener('click', change, false);
}
}
var clear = function() {
var menuElements = document.querySelectorAll('[data-tab]');
for (var i = 0; i < menuElements.length; i++) {
menuElements[i].classList.remove('active');
var id = menuElements[i].getAttribute('data-tab');
document.getElementById(id).classList.remove('active');
}
}
var change = function(e) {
clear();
e.target.classList.add('active');
var id = e.currentTarget.getAttribute('data-tab');
document.getElementById(id).classList.add('active');
}
bindAll();
}
var connectTabs = new Tabs();
.b-box {margin-top: 1500px;}
.b-tab {
padding: 20px;
border: 1px solid #000;
display: none
}
.b-tab.active {
display: block;
}
.b-nav-tab {
display: inline-block;
padding: 20px;
}
.b-nav-tab.active {
color: #ff4200;
}
<a href="#orange" data-tab="orange" class="b-nav-tab active">
Orange
</a>
<a href="#green" data-tab="green" class="b-nav-tab">
Green
</a>
<a href="#blue" data-tab="blue" class="b-nav-tab">
Blue
</a>
<div class="b-box">
<div id="orange" class="b-tab active">
Orange tab content
</div>
<div id="green" class="b-tab">
Green tab content
</div>
<div id="blue" class="b-tab">
Blue tab content
</div></div>
I updated your code.
Actually you was showing # sign in href so it redirect the position to that box. I removed it.
Good Luck.
'use strict';
function Tabs() {
var bindAll = function() {
var menuElements = document.querySelectorAll('[data-tab]');
for (var i = 0; i < menuElements.length; i++) {
menuElements[i].addEventListener('click', change, false);
}
}
var clear = function() {
var menuElements = document.querySelectorAll('[data-tab]');
for (var i = 0; i < menuElements.length; i++) {
menuElements[i].classList.remove('active');
var id = menuElements[i].getAttribute('data-tab');
document.getElementById(id).classList.remove('active');
}
}
var change = function(e) {
clear();
e.target.classList.add('active');
var id = e.currentTarget.getAttribute('data-tab');
document.getElementById(id).classList.add('active');
}
bindAll();
}
var connectTabs = new Tabs();
.b-tab {
padding: 20px;
border: 1px solid #000;
display: none;
}
.b-tab.active {
display: block;
}
.b-nav-tab {
display: inline-block;
padding: 20px;
}
.b-nav-tab.active {
color: #ff4200;
}
<a href="javascript:void(0)" data-tab="orange" class="b-nav-tab active">
Orange
</a>
<a href="javascript:void(0)" data-tab="green" class="b-nav-tab">
Green
</a>
<a href="javascript:void(0)" data-tab="blue" class="b-nav-tab">
Blue
</a>
<div id="orange" class="b-tab active">
Orange tab content
</div>
<div id="green" class="b-tab">
Green tab content
</div>
<div id="blue" class="b-tab">
Blue tab content
</div>
One way would be to add this e.preventDefault(); to your change function and the other way would be to replace href="#orange" with href="javascript:void(0)". All the same with other hrefs.

Change active state on scroll to viewport

I'm trying to make a single static website, which when an div child of comes into viewport (precisely, when div element comes into the upper 50% of the viewport) changes the corresponding div's class in side-nav to "active". It should work scrolling down and up.
So far I've tried several solution from other threads on SO, none successful. I assume I've been approaching this wrong.
$(window).on('scroll', function() {
$("#vars-args").each(function() {
if (elementInViewport2($(this))) {
$(this).find("#div1a").addClass("active");
}
});
});
function elementInViewport2(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while (el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
);
}
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<div id="side-nav">
1
2
3
4
5
6
</div>
<div id="content">
<div id="div1">
<!--content-->
</div>
<div id="div2">
<!--content-->
</div>
<div id="div3">
<!--content-->
</div>
<div id="div4">
<!--content-->
</div>
<div id="div5">
<!--content-->
</div>
<div id="div6">
<!--content-->
</div>
</div>
Also note that content of each div inside can be larger than the size of viewport.
I have been having problems getting the javascript to work. Also please note that the current JS is copied from some other thread.
This can be achieved using the IntersectionObserver as told by #cloned in the comments: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
To achieve this, you need a callback function passed as a parameter which is executed once isIntersecting is true, an option object (below it sets the threshold at 50% of the element) and an IntersectionObserver.
The callback toggles the active class to the a element according to the entry's id.
At the end we loop through the divs and make our observer observe them.
const callback = (entries, observer) => {
entries.forEach(entry => {
const navItem = document.querySelector('#' + entry.target.id + 'a');
if (entry.isIntersecting) {
console.log(navItem.getAttribute('id'));
navItem.classList.add('active');
} else {
navItem.classList.remove('active');
}
});
};
const options = {
threshold: 0.5
};
const observer = new IntersectionObserver(callback, options);
const container = document.getElementById('content');
const targetElements = container.querySelectorAll('div');
targetElements.forEach(element => {
observer.observe(element);
});
Here is a JSBin to demonstrate it https://jsbin.com/riyuhediso/47/edit?html,js,console,output
Note that although it demonstrates its feasibility it's not been profiled for performance issues which can be significant so I don't vouch for it.
If you are using Bootstrap you can use the ScrollSpy lib https://getbootstrap.com/docs/4.1/components/scrollspy/ and there is also ScrollMagic which is great http://scrollmagic.io/
You need to filter out which element is inside the viewport with the help of .getBoundingClientRect()
Checkout this
and check if any content has it's top and bottom within the half of the viewport ( window.innerHeight )
I took help of filter function to find out the index of contents that is within the built in function and set the .active class of the corresponding anchor.
Have a look at the snippet:
var direction = 0; // a variable to keep track of scrolled position;
$(window).on('scroll', function() {
// check if window is scrolling up or down;
if ($(window).scrollTop() > direction) { // if true, window scrolling scrolling down;
$('#side-nav').find('a').removeClass('active'); // remove active class from all anchors
$('#side-nav').find('a').eq(
// .eq() selector helps to find elements with index number, and here we pass a filter to find the content that is within the viewport;
$('#content').find('div').filter(function(index) {
return this.getBoundingClientRect().y <= (window.innerHeight / 2) && this.getBoundingClientRect().y + this.getBoundingClientRect().height > window.innerHeight / 2;
}).index()
).addClass('active');
// update the current scroll position now;
direction = $(window).scrollTop();
} else { // if false, window scrolling scrolling up;
$('#side-nav').find('a').removeClass('active'); // remove active class from all anchors
$('#side-nav').find('a').eq(
$('#content').find('div').filter(function(index) {
return this.getBoundingClientRect().y < (window.innerHeight / 2) && this.getBoundingClientRect().y + this.getBoundingClientRect().height > window.innerHeight / 2;
}).index()
).addClass('active');
// update the current scroll position now;
direction = $(window).scrollTop();
}
});
* {
margin: 0;
padding: 0;
}
#side-nav {
/* feel free to remove or change, only for testing */
position: fixed;
width: 100%;
top: 0;
padding: 15px;
}
#side-nav a {
/* feel free to remove, only for testing */
text-decoration: none;
color: grey;
margin-right: 5px;
font-size: 24px;
font-weight: bold;
}
#side-nav a.active {
color: #000;
/* sets color for the default active class */
}
#content div {
min-height: 600px;
background-color: #cecece;
border-bottom: 1px solid #fff;
box-sizing: border-box;
padding: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="side-nav">
<a href="" id="div1a" class='active'>1</a>
<!-- set a default class assuming the first one will be in viewport while window loads -->
2
3
4
5
6
</div>
<div id="content">
<div id="div1">
<p>One</p>
</div>
<div id="div2">
<p>Two</p>
</div>
<div id="div3">
<p>Three</p>
</div>
<div id="div4">
<p>Four</p>
</div>
<div id="div5">
<p>Five</p>
</div>
<div id="div6">
<p>Six</p>
</div>
</div>

creating a rolling menu: rolling just once

[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>

How can I change the x position of a div via javascript when I click on another div this way?

<body>
<div id = "SiteContainer">
<div id = "NavigationButtons"></div>
<div id = "ShowReelContainer">
<div id= "NavigationBackward" name = "back" onclick="setPosition();">x</div>
<div id= "NavigationForward" name = "forward" onclick="setPosition();">y</div>
<div id = "VideoWrapper">
<div id = "SlideShowItem">
<img src="Images/A.png" alt="A"></img>
</div>
<div id = "SlideShowItem">
<img src="Images/B.png" alt="B"></img>
</div>
<div id = "SlideShowItem">
<img src="Images/C.png" alt="C" ></img>
</div>
</div>
</div>
</div>
<script>
var wrapper = document.querySelector("#VideoWrapper");
function setPosition(e)
{
if(e.target.name = "forward")
{
if!(wrapper.style.left = "-200%")
{
wrapper.style.left = wrapper.style.left - 100%;
}
}
else
{
if(e.target.name = "back")
{
if!(wrapper.style.left = "0%")
{
wrapper.style.left = wrapper.style.left + 100%;
}
}
}
}
</script>
</body>
Hi, I am very new to javascript. What I am trying to do, is change the x-position of a div when another div (NavigationForward or NavigationBackward) is clicked. However it does not appear to do anything at all. Basically if the div with name forward is clicked, I want to translate the VideoWrapper -100% from it's current position and +100% when "back". The css div itself VideoWrapper has a width of 300%. Inside this div as you can see is a SlideShowItem which is what will change. Perhaps I am adding and subtracting 100% the wrong way?
EDIT:
Thanks everyone for helping me out with this...I had just one more query, I am trying to hide the arrows based on whether the wrapper is at the first slide or the last slide. If its on the first slide, then I'd hide the left arrow div and if it's on the last, I'd hide the right arrow, otherwise display both of em. Ive tried several ways to achieve this, but none of em work, so Ive resorted to using copies of variables from the function that works. Even then it does not work. It appears that my if and else if statements always evaluate to false, so perhaps I am not retrieving the position properly?
function HideArrows()
{
var wrapper2 = document.getElementById("VideoWrapper");
var offset_x2 = wrapper2.style.left;
if(parseInt(offset_x2,10) == max_x)
{
document.getElementById("NavigationForward").display = 'none';
}
else if(parseInt(offset_x2,10) == min_x)
{
document.getElementById("NavigationBackward").display = 'none';
}
else
{
document.getElementById("NavigationForward").display = 'inline-block';
document.getElementById("NavigationBackward").display = 'inline-block';
}
}
//html is the same except that I added a mouseover = "HideArrows();"
<div id = "ShowReelContainer" onmouseover="HideArrows();">
To achieve this type o slider functionality your div VideoWrapper must have overflow:hidden style, and your SlideShowItemdivs must have a position:relative style.
Then to move the slides forward or backward you can use the style left which allows you to move the divs SlideShowItem relative to it's parent VideoWrapper.
I've tested this here on JSFiddle.
It seems to work as you described in your question, although you may need to do some adjustments, like defining the width of your slides, how many they are and so on.
For the sake of simplicity, I defined them as "constants" on the top of the code, but I think you can work from that point on.
CSS
#VideoWrapper{
position:relative; height:100px; white-space:nowrap;width:500px;
margin-left:0px; border:1px solid #000; overflow:hidden; }
.SlideShowItem{
width:500px; height:100px;display:inline-block;position:relative; }
#NavigationForward, #NavigationBackward{
cursor:pointer;float:left; background-color:silver;margin-right:5px;
margin-bottom:10px; text-align:center; padding:10px; }
HTML
<div id = "SiteContainer">
<div id = "NavigationButtons">
</div>
<div id = "ShowReelContainer">
<div id= "NavigationBackward" name = "back" onclick="setPosition('back');">prev</div>
<div id= "NavigationForward" name = "forward" onclick="setPosition('forward');">next</div>
<div style="clear:both;"></div>
<div id = "VideoWrapper">
<div class= "SlideShowItem" style="background-color:blue;">
Slide 1
</div>
<div class = "SlideShowItem" style="background-color:yellow;">
Slide 2
</div>
<div class = "SlideShowItem" style="background-color:pink;">
Slide 3
</div>
</div>
</div>
</div>
JavaScript
var unit = 'px'; var margin = 4; var itemSize = 500 + margin; var itemCount = 3; var min_x = 0; var max_x = -(itemCount-1) * itemSize;
function setPosition(e) {
var wrapper = document.getElementById("VideoWrapper");
var slides = wrapper.getElementsByTagName('div');
var offset_x = slides[0].style.left.replace(unit, '');
var curr_x = parseInt(offset_x.length == 0 ? 0 : offset_x);
if(e == "forward")
{
if(curr_x <= max_x)
return;
for(var i=0; i<slides.length; i++)
slides[i].style.left= (curr_x + -itemSize) + unit;
}
else if(e == "back")
{
if(curr_x >= min_x)
return;
for(var i=0; i<slides.length; i++)
slides[i].style.left= (curr_x + itemSize) + unit;
} }
After you analyze and test the code, I don't really know what's your purpose with this, I mean, you maybe just playing around or trying to develop something for a personal project, but if you are looking for something more professional avoid to create things like sliders on your own, as there are tons of plugins like this available and well tested out there on the web.
Consider using jQuery with NivoSlider, it works like a charm and is cross browser.
I would recommend using jQuery, this will reduce your coding by quite a bit. Can read more here: http://api.jquery.com/animate/
I've created a simple fiddle for you to take a look at. This example uses the .animate() method to reposition two div elements based on the CSS 'left' property.
CSS:
#container {
position: absolute;
left: 1em;
top: 1em;
right: 1em;
bottom: 1em;
overflow: hidden;
}
#one, #two {
position: absolute;
color: white;
}
#one {
background: pink;
width: 100%;
top:0;
bottom:0;
}
#two {
background: blue;
width: 100%;
left: 100%;
top:0;
bottom:0;
}
HTML:
<div id="container">
<div id="one">Div One</div>
<div id="two">Div Two</div>
</div>
JavaScript/jQuery:
var one, two, container;
function animateSlides(){
one.animate({
left : '-100%'
}, 1000, function(){
one.animate({
left : 0
}, 1000);
});
two.animate({
left : 0
}, 1000, function(){
two.animate({
left:'100%'
}, 1000);
});
};
$(function(){
one = $('#one');
two = $('#two');
container = $('#container');
setInterval(animateSlides, 2000);
});
JSFiddle Example: http://jsfiddle.net/adamfullen/vSSK8/3/

Categories

Resources