Class won't toggle on scroll - javascript

Can someone assist me with this? Whenever I try to scroll, the class none doesn't toggle..
window.addEventListener('scroll', function() {
var header = document.getElementsById("here");
header.classList.toggle("none", window.scrollY > 0);
});
.none {
display: none;
}
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/800px-Image_created_with_a_mobile_phone.png" id="here>

You simple didn't close id of img and write elementsbyid instead of elementbyid.
window.addEventListener('scroll', function() {
var header = document.getElementById("here");
header.classList.toggle("none", window.scrollY > 0);
});
.none {
display: none;
}
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/800px-Image_created_with_a_mobile_phone.png" id="here">

Related

Smoothly scroll element from current position

I have written the following code to scroll an element 20 more pixels to the right.
const button = document.getElementById('slide');
button.onclick = function () {
document.getElementById('container').scrollLeft += 20;
};
How can I make the scrolling smooth? I have tried using Element#scroll like so:
const button = document.getElementById('slide');
button.onclick = function () {
document.getElementById('container').scroll({
left: += 20,
behavior: smooth
});
};
Am I able to do this?
You can use Element#scrollBy to scroll a certain amount from the current position.
button.onclick = function () {
document.getElementById('container').scrollBy({
left: 20,
behavior: 'smooth'
});
};
Is this what you are looking for?
From MDN:
scrollBy() scrolls by a particular amount, whereas scroll() scrolls to an absolute position in the document.
https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy
const container = document.querySelector("#container");
const button = document.querySelector("#btnScroll");
button.addEventListener('click', e => {
container.scrollBy({
left: 200,
behavior: 'smooth'
});
});
#container {
position: relative;
max-width: 200px;
overflow-x: scroll;
display: flex;
margin: 20px;
}
img {
display: inline-block
}
<div id="container">
<img src="https://dummyimage.com/200x100/000/fff">
<img src="https://dummyimage.com/200x100/0f0/000">
<img src="https://dummyimage.com/200x100/00f/fff">
<img src="https://dummyimage.com/200x100/f00/fff">
</div>
<button id="btnScroll">Scroll 200px</button>

Modify code to take textContent from li instead of thumbnail img src?

I found (and tweaked) the code below that was designed for switching the larger img src with the src of thumbnails in a list, but I'm not sure how to adjust it to use something like https://picsum.photos/id/CLICKED_LI_textContent/200/200 as the URL instead of pulling from a thumbnail's src.
For some more context here's the original post in which I was looking into this
How can I change img src from list of (non-image) items?
I haven't taken any JS classes, so I'm not sure how every component of the script works. I'm more comfortable with pure HTML and CSS, but think JS is the answer for making this work more smoothly.
(I did add the jquery script src to the document for this)
Sorry the code is a little ugly, I would have added the script and style tags and such but I ran out of time while posting this
$("#list li").click(function(e) {
// if i use this getting undefined
// var src = $(this).attr("src");
// so i use this method
var target = e.target;
var src = target.src;
console.log(src);
$("#display").fadeOut(function() {
$(this).on('load', function() {
$(this).fadeIn();
});
$(this).attr("src", src);
});
//record which thumb was clicked
$("#list li").removeClass("active"); //remove class
$(this).addClass("active"); //apply class to selected thumb
});
//move next
$("#left-arrow").click(function() {
if ($("#list li.active").next("#list li").length > 0) {
$("#list li.active").next().children( 'img' ).trigger("click");
} else {
$("#list li:first > img").trigger("click"); //go to first
}
return false;
});
//move previous
$("#right-arrow").click(function() {
if ($("#list li.active").prev("#list li").length > 0) {
$("#list li.active").prev().children( 'img' ).trigger("click");
} else {
$("#list li:last > img").trigger("click"); //go to end
}
return false;
});
//click the first thumb to begin
$("#list li:first > img").trigger("click");
.container {
display: flex;
}
.active {
border-bottom: 1px solid #990000;
}
.list {
width: 200px;
cursor: pointer;
padding: 0.25rem;
}
list > li * {
/* so only the li tag can be event.target, and none of it's children */
pointer-events: none;
}
.display {
max-width: 500px;
max-height: 500px;
}
<div class="container">
<div class="list">
<ul id="list">
<li>237</li>
<li>240</li>
<li>100</li>
<li>301</li>
</ul>
$larr; $rarr;
</div>
<div class="show">
<img src="https://picsum.photos/id/237/200/200" class="display" id="display">
</div>
</div>
Here is a pure javascript solution. The only difference is that it lacks the fading between the images.
I tried to write the code as pedagogic as possible, using variables as explanations. The code goes more with your original thread, where you had a bunch of images with different file endings. I gave the image an alt attribute, so you can see the change.
A short explanation:
Use an array for the images.
Create your list through javascript, using the array.
Add click listeners to your #list, where you read the .textContent. I added pointer-events: none; to any children to the li tags so they don't trigger the click listener.
Add click listeners to your prev/next buttons, where you check which index that the currently visible image has in the array (from 0 to 3 in imageArr) and then adds +1 och -1 to that index.
[edit] Added code for updating the CSS.
const listEl = document.getElementById('list');
const imgElement = document.querySelector('.right > img');
let imageArr = ["237.jpg", "240.gif", "100.jpeg", "301.png"]; // 1
let currentImage = '';
document.getElementById('next').addEventListener('click', () => shiftImage(1));
document.getElementById('prev').addEventListener('click', () => shiftImage(-1));
listEl.addEventListener('click', displayImage);
function updateImage(imageName) {
const subfolder = 'images/';
changeActive(imageName, currentImage); /* ADDED in EDIT */
currentImage = imageName;
imgElement.src = subfolder + imageName;
imgElement.alt = imageName;
}
/* ADDED in EDIT */
function changeActive(newImage, oldImage) {
if (oldImage) {
let oldIndex = imageArr.indexOf(oldImage);
toggleActiveClass(oldIndex);
}
let currentIndex = imageArr.indexOf(newImage);
toggleActiveClass(currentIndex);
}
/* ADDED in EDIT */
function toggleActiveClass(imageIndex) {
let liElements = listEl.childNodes;
liElements[imageIndex].classList.toggle('active');
}
function shiftImage(direction) {
let currentIndex = imageArr.indexOf(currentImage);
let newIndex = currentIndex + direction;
if (newIndex < 0) { newIndex = imageArr.length - 1; }
else if (newIndex >= imageArr.length) { newIndex = 0; }
let newImageName = imageArr[newIndex];
updateImage(newImageName);
}
function displayImage(event) {
let liElement = event.target;
updateImage(liElement.textContent);
}
function constructImageLinks() { // 2
let htmlOutput = '';
for (let imageSrc of imageArr) {
htmlOutput += `<li>${imageSrc}</li>`;
}
listEl.innerHTML = htmlOutput;
}
constructImageLinks();
updateImage(imageArr[0]);
section {
display: flex;
}
section ul {
margin-top: 0px;
}
section > .left li {
cursor: pointer;
padding: 0.25rem;
}
section > .left li.active {
background-color: pink;
}
section > .left li > * {
pointer-events: none;
}
section > div {
padding: 1rem;
}
section > .right > img {
width: 200px;
border: 1px solid;
padding: 0.5rem;
}
<section>
<div class="left">
<ul id="list"></ul>
<button id="prev">Previous</button>
<button id="next">Next</button>
</div>
<div class="right">
<img>
</div>
</section>
JSFiddle - Link
HTML
<div class="container">
<div class="list">
<ul id="list">
<li>237</li>
<li>240</li>
<li>100</li>
<li>301</li>
</ul>
$larr; $rarr;
</div>
<div class="show">
<img src="https://picsum.photos/id/240/200/200" class="display" id="display">
</div>
</div>
Javascript
// HELPER FUNCTIONS
function getImageURL(id, width=200, height=200){
return "https://picsum.photos/id/"+ id + "/" + width + "/" + height;
}
function removeActive(){
let lis = $('#list li');
for(let i=0;i<lis.length;i++){
$(lis[i]).removeClass('active');
}
}
// HANDLE EVENTS
$(document).on('click', "#list li", async (e)=>{
await $('#display').fadeOut();
removeActive();
let li = $(e.target);
li.addClass('active');
let image_id = parseInt($(e.target).html());
let image_url = getImageURL(image_id);
$('#display').attr('src', image_url);
await $('#display').fadeIn();
});
//move next
$(document).on('click', "#left-arrow", (e)=>{
// Handler Here
});
//move previous
$(document).on('click', "#right-arrow", (e)=>{
// Handler Here
});
CSS
.active {
border-bottom: 1px solid #990000;
}
.list {
width: 200px;
cursor: pointer;
padding: 0.25rem;
}
list > li * {
/* so only the li tag can be event.target, and none of it's children */
pointer-events: none;
}
.display {
max-width: 500px;
max-height: 500px;
}
.container {
display: flex;
}

Show logo if site has scrolled

I have a header with a logo. This logo should appear only if the site has been scrolled.
I tried this in javascript:
if(document.getElementById("div").scrollTop != 0){
document.write("<img src='logo.jpg'>");
}
But this did not work.
How to achieve it?
Use window.addEventListener('scroll', callback) and then set the value "block" to the img's property.
window.addEventListener('scroll', function(e) {
if (document.getElementsByTagName("html")[0].scrollTop > 5) {
document.getElementsByClassName('imgHeader')[0].style.display = "block";
} else {
document.getElementsByClassName('imgHeader')[0].style.display = "none";
}
});
.imgHeader {
height: 100px;
width: 100px;
display: none;
}
div {
height: 1000px;
}
header {
position: fixed;
top: 0;
width: 100%;
}
<header><img class="imgHeader" src="https://material.angular.io/assets/img/examples/shiba1.jpg" /></header>
<div></div>
Try this one
$(document).on("scroll", function() {
if ($(document).scrollTop() > 5) {
$(".below-top-header").addClass("show-class");
} else {
$(".below-top-header").removeClass("show-class");
}
});
.content {
height: 500px;
}
.show-class {
position: fixed;
display: block !important;
}
.hide-class {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<div class="below-top-header hide-class">
Image
</div>
</div>
Unfortunately, I think you must use some JavaScript to make it work like you want.
Here is an easy snippet to show the principle I used:
Start with the logo already in the html, but with display: none in its CSS,
Use window.addEventListener('scroll', callback) to change display: none to display: block when the page is scrolled down (i.e. document.documentElement.scrollTop > 0).
var logo = document.getElementById('logo');
window.addEventListener('scroll', function(e) {
if (document.documentElement.scrollTop > 0) {
logo.style.display = 'block';
}else logo.style.display = 'none';
});
#logo {
display: none;
position: fixed;
top: 0;
background: #aaa;
}
#page {
background: #ddd;
height: 2000px;
}
<div id='logo'><img src='http://placekitten.com/200/50'></div>
<div id='page'>Start of page<br>Try to scroll down</div>
Hope it helps.
You need to add an scrollListener to the window in order to execute code when the user scrolls.
Your code only gets executed on page load.
Informations on Eventlisteners: https://developer.mozilla.org/de/docs/Web/API/EventTarget/addEventListener
window.addEventListener('scroll', function(e) {
//do something as soon as the window was scrolled
});
Be aware that the event will be triggered each time the user scrolls.

How do I change the properties of a <div> with a toggled class?

I have a <div class="content toggle"> that I have hidden until a certain event is called, and then I add a class to it to show that it needs to be visible.
My current CSS looks like:
.content {
display: none;
}
.content.visible {
display: block;
}
My code for adding .visible looks like this:
[].forEach.call(document.getElementsByClassName('toggle'), function(x) {
x.classList.toggle('visible');
});
But, when the class .visible is added, the <div> is still display: none;. What's happening here? How can I fix it?
seems like your JS selects a class called "toggle" instead of "content":
getElementsByClassName('toggle')
There's 100 ways do what you want. Here's one solution.
<script>
function makeVisible() {
var myContentDiv = document.getElementById("mycontent");
myContentDiv.style.display = "block";
}
</script>
<div id="mycontent" class="content"></div>
<a id="mybutton" href="javascript:makeVisible()"></a>
Updated answer, to reflect the jsfiddle.
HTML:
<div class="content">hi</div>
<button id='button'>toggle visible</button>
JS
var button = document.getElementById('button');
button.onclick = function() {
var div = document.getElementById('content');
if (div.style.display !== 'none') {
div.style.display = 'none';
}
else {
div.style.display = 'block';
}
};
.content {
display: none;
}
.visible {
display: block;
}
?
Keep your display classes separate from your core class.
in jQuery:
$(this).toggleClass("visible hidden");
and the css:
<style>
.visible {
display: block;
}
.hidden {
display: none;
}
</style>

.is() not working as intended

I'm new to jQuery, practicing with a slideshow and trying to make it repeat. For some reason if ( last.is(active) ) is never returning true. In inspector I can see that the last child is getting the active ID. Is this not how it's meant to be used? if (active != last) didn't work either.
Fiddle
JS
function changeImage() {
var active = $('#active');
var first = $('#slideshow:nth-child(1)');
var last = $('#slideshow:nth-last-child(1)');
if ( last.is(active) ) {
var next = first;
} else {
var next = active.next();
}
next.attr('id', 'active');
active.attr('id', 'inactive');
}
setInterval(changeImage, 1000);
Markup
<div id="slideshow">
<img id="active" src="https://i.imgur.com/8iOuvtf.jpg">
<img src="https://i.imgur.com/Wi8mlH2.jpg">
<img src="https://i.imgur.com/MNhgqco.jpg">
</div>
CSS
#slideshow img {display: none;}
#slideshow #active {
display: block;
width: 100%;
height: auto;
}
I put this fiddle together for you.
https://jsfiddle.net/76xg0d7L/
It is much easier to work with classes than IDs in this situation. I have modified your changeImage() function.
function changeImage() {
var $next = $('.slide.active').removeClass('active').next('.slide');
if ($next.length) {
$next.addClass('active');
}
else {
$('.slide:first').addClass('active');
}
}
setInterval(changeImage, 1000);
I've also update your CSS to select the active class, as opposed to the ID.
#slideshow img {display: none;}
#slideshow .active {
display: block;
width: 100%;
height: auto;
}
Let me know if you have any questions or if this works for you.
You should use it more like
function changeImage() {
var active = $("[state='active']");
var next = active.is(":last") ? $("#slideshow:first-child") : active.next();
active.data("state", "inactive"); //don't multiply same id attribute
next.data("state", "active");
}
setInterval(changeImage, 1000);
https://jsfiddle.net/gm9twq6j/
You should pass around a class called "active" using .addClass, .removeClass, and .hasClass instead of what you are trying to do with swapping out IDs.
JS:
function changeImage() {
var active = $('#slideshow').find('.active');
var first = $('#slideshow img:first-child');
var last = $('#slideshow img:last-child');
if ( last.hasClass('active') ) {
var next = first;
} else {
var next = active.next();
}
active.removeClass('active');
next.addClass('active');
}
setInterval(changeImage, 1000);
CSS:
#slideshow img {display: none;}
#slideshow .active {
display: block;
width: 100%;
height: auto;
}
HTML:
<div id="slideshow">
<img class="active" src="https://i.imgur.com/8iOuvtf.jpg">
<img src="https://i.imgur.com/Wi8mlH2.jpg">
<img src="https://i.imgur.com/MNhgqco.jpg">
</div>

Categories

Resources