I've built this gallery
https://jsfiddle.net/ramamamagagaulala/do4yLxcz/
let images = document.querySelectorAll('.work-item');
let best = document.querySelector('.work-modal');
let main = document.querySelector('.work-modal__item');
console.log(images)
let closeButton = document.getElementById("closee");
images.forEach(function(ref) {
ref.addEventListener('click', function(){
let newImage = this.getElementsByTagName('img')[0].src;
best.classList.add('work-modal--show');
main.style.backgroundImage = `url( ${newImage} )`;
})
})
closeButton.addEventListener('click', function() {
best.classList.remove('work-modal--show');
});
basically, it works like this:
you click an item.
JavaScript checks what IMG this item contains.
a modal window opens up.
then the IMG that is associated with the item, is going to be displayed as the background image of this modal.
So far so good, however, I would like to build a function so I can press the arrow keys on my keyboard and the next image is going to be displayed.
What I've tried is to select the IMG of the nextSibling while clicking. Then I have used this variable to set up the background image of the modal window. But this only worked once.
Any ideas what to try next?
I would suggest have list of images urls in an array in .js file, and then you show one modal, click right/left and just change img src value to next/previous array element, untill get to either end of array.
There are three things we need to do for this problem
Storing the image source in an array
Keep track of the position of the image index
Add an event listener to track the keypress for next & prev button on your keyboard
let images = document.querySelectorAll('.work-item');
let best = document.querySelector('.work-modal');
let main = document.querySelector('.work-modal__item');
let closeButton = document.getElementById("closee");
let currentIndex = -1;
let imgSrc = [];
images.forEach(function(ref,index) {
imgSrc.push(ref.children[0].getAttribute("src"));
ref.addEventListener('click', function(){
let newImage = this.getElementsByTagName('img')[0].src;
best.classList.add('work-modal--show');
main.style.backgroundImage = `url( ${newImage} )`;
currentIndex = index
});
})
closeButton.addEventListener('click', function() {
best.classList.remove('work-modal--show');
});
let doc = document.getElementById("work");
window.addEventListener("keydown", event => {
if(event.keyCode === 39){
// next event
if(currentIndex < imgSrc.length -1 ){
main.style.backgroundImage = `url( ${imgSrc[currentIndex+1]} )`;
currentIndex=currentIndex+1;
} else {
alert("Reached last image")
}
} else if(event.keyCode === 37){
// prev event
if(currentIndex > 0){
main.style.backgroundImage = `url( ${imgSrc[currentIndex-1]} )`;
currentIndex=currentIndex-1;
} else {
alert("Reached first image")
}
}
});
.work-container{
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 1rem;
}
img {
width: 250px;
}
.work-item__img{
width: 100%;
height: 100%;
display: block;
transition: all 1s linear;
opacity: 1;
object-fit: cover;
transform: scale(1.1);
}
/* modal */
.work-modal{
display: none;
}
.work-modal--show{
position: fixed;
background: rgba(0,0,0,0.5);
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 999;
display: grid;
justify-content: center;
align-items: center;
}
.work-modal__item{
height: 70vh;
width: 80vw;
border:0.5rem solid var(--yellow);
border-radius: 0.4rem;
}
#media screen and (min-width:768px){
.work-modal__item{
height: 80vh;
width: 60vw;
}
}
.work-modal__close{
position: fixed;
font-size: 3rem;
color: var(--brightYellow);
bottom: 5%;
right: 5%;
transition: color 0.5s linear;
cursor: pointer;
text-decoration: none;
display: inline-block;
}
.work-modal__close:hover{
color: red;
}
<section class="work section-padding" id="work">
<div class="work-container">
<div class="work-item item-1">
<img src="https://images.pexels.com/photos/2683138/pexels-photo-2683138.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="" class="work-item__img">
</div>
<div class="work-item item-2">
<img src="https://images.pexels.com/photos/2736220/pexels-photo-2736220.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="" class="work-item__img">
</div>
<div class="work-item item-3">
<img src="https://images.pexels.com/photos/2928178/pexels-photo-2928178.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="" class="work-item__img">
</div>
</div>
</section>
<div class="work-modal">
<div class="work-modal__item"></div>
<div class="work-modal__close">
<i id="closee" class="fas fa-window-close">close</i>
</div>
</div>
JS Fiddle
https://jsfiddle.net/aamin89/b5wp3kez/1/
Related
I am trying to add arrows to my simple lightbox. The arrows are simple symbols "<" and ">. I have created them with jquery and when I try to add them to the image, they show up in the developer tools but not in the website for whatever reason. Can you tell me what's the problem please?
Here is the screenshot of the issue, if you did not understand my poor english. As you can see, the arrows are created in developer tools, but they cannot be found on the website. https://prnt.sc/26lyfbc
//Gallery Lightbox made with Jquery
let gallery = $('#gallery'),
overlay = $('<div = id = "overlay"></div>').appendTo('body').hide();
//Opens the lightbox with chosen image
gallery.find('a').on("click", function(event){
event.preventDefault();
let href = $(this).attr('href'),
image = $('<img>', {src: href}),
larrow = $('<div = id = "larrow"> < </div>'); //LEFT ARROW
rarrow = $('<div = id = "rarrow"> > </div>'); //RIGHT ARROW
image.appendTo(overlay);
larrow.appendTo(image);
overlay.show();
//Closes the Lightbox with the image, by clicking on the overlay
$(document).on("click", "#overlay", function(){
overlay.hide();
image.remove();
})
})
.gallery {
display: none;
opacity: 0;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
width: 1004px;
margin: 0 auto;
}
.gallery img {
position: relative;
top: 100px;
height: 200px;
width: 300px;
margin: 0 1em;
}
#overlay {
background: rgba(0, 0, 0, .7);
position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
text-align: center;
z-index: 10;
}
#overlay img {
margin-top: 5%;
border: solid 5px white;
border-radius: 5px;
}
//Dont mind these, the silly values are just for testing purposes
#larrow {
font-size: 500px;
color: red;
z-index: 2000;
}
#rarrow {
font-size: 500px;
color: red;
z-index: 2000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="gallery" id="gallery">
<img src="img\placeholder1.jpg" alt="">
<img src="img\placeholder2.jpg" alt="">
<img src="img\placeholder3.jpg" alt="">
<img src="img\placeholder4.jpg" alt="">
<img src="img\placeholder5.jpg" alt="">
<img src="img\placeholder6.jpg" alt="">
</div>
</body>
You have a few errors in your code. Instead of
larrow = $('<div = id = "larrow"> < </div>'); //LEFT ARROW
rarrow = $('<div = id = "rarrow"> > </div>'); //RIGHT ARROW
You should write it like this. There is no need for the '=' between div and id.
larrow = $('<div id = "larrow"> < </div>'); //LEFT ARROW
rarrow = $('<div id = "rarrow"> > </div>'); //RIGHT ARROW
The same goes for the following tags:
overlay = $('<div id = "overlay"></div>').appendTo('body').hide();
Putting the div tags in the image will also not work. Instead you should put the image and the arrows in a container together like this:
<div id="overlay">
<img src ... </img>
<div id = "larrow"> < </div>
<div id = "rarrow"> > </div>
</div>
Refer to Floating Div Over An Image to see the needed css.
I am making a website that has multiple layers to it, which is brought back and forth by manipulating the z-index in Javascript through event reactions (like onclick). I have a navigation bar which has a large z-index value compared to every other element as I would like it to be at the very front regardless of anything. However, when run on Safari, the nav bar disappears from the get go, while it works fine on Google Chrome and FireFox.
I have included the css code and javascript code that dictates this role:
JAVASCRIPT:
//Global variables representing DOM elements
var introTitleElem = document.getElementById('introduction-title');
var resumeElem = document.getElementById('resume-container');
var introElem = document.getElementById('intro-content');
var eduElem = document.getElementById('edu-content');
//Layer tracker (for transition effect)
var prev = introElem;
var prevButton = "";
//Function that actually changes the layers
function changeLayer(layer, button) {
if (layer === prev) return;
introTitleElem.style.opacity = "0";
prev.style.zIndex = "40";
layer.style.zIndex = "50";
layer.style.cssText = "opacity: 1; transition: opacity 0.5s";
prev.style.zIndex = "5";
prev.style.opacity = "0";
prev = layer;
if (prevButton !== "") prevButton.style.textDecoration = "none";
button.style.textDecoration = "underline";
prevButton = button;
}
//Manages events triggered by name button toggle
function revealResume() {
introTitleElem.style.zIndex = "0";
resumeElem.style.zIndex = "10";
resumeElem.style.opacity = "1";
introElem.style.opacity = "1";
resumeElem.style.transition = "opacity 0.7s";
introElem.style.transition = "opacity 0.7s";
}
document.getElementById("name-title").addEventListener("click", revealResume);
//Manage z-index of different components of the resume and reveal them accordingly
$('#nav-education').click(function () {
onEducation = true;
changeLayer(eduElem, this);
});
CSS (SASS):
/*NAVIGATION STYLING*/
#fixed-nav {
align-self: flex-start;
overflow-x: hidden;
float: right;
z-index: 9999 !important;
display: flex;
margin: 1em;
li {
margin: 0.6em;
font: {
family: $font-plex-sans-condensed;
size: 0.8em;
}
text-align: center;
color: $lightest-grey;
transition: color 0.3s;
&:hover {
cursor: pointer;
color: $dark-grey;
transition: color 0.3s;
}
}
}
/*OVERALL DIV FORMATTING*/
.format-div {
width: 100vw;
height: 100vh;
display: flex;
position: absolute;
justify-content: center;
align-items: center;
flex-direction: column;
opacity: 0;
}
/*EDUCATION CONTENT STYLING*/
#edu-content {
background-color: $red-1;
}
HTML:
<div id="resume-container">
<ul id="fixed-nav">
<li id="nav-education">education.</li>
<li id="nav-experiences">experiences.</li>
<li id="nav-skills">skills.</li>
<li id="nav-projects">projects.</li>
<li id="nav-additional">additional.</li>
<li id="nav-contact">contact.</li>
</ul>
<div id="intro-content" class="format-div">
<h1 class="type-effect">
<h1>I'm Daniel <b>(Sang Don)</b> Joo</h1>
<span class="blinking-cursor">|</span>
</h1>
</div>
<div id="edu-content" class="format-div">
<h1>education</h1>
</div>
Sorry about the large amount of code but I'm really unsure of where this problem is rooted. Cheers!
it has to be the position feature of the elements so that it can work
wrong example ( not working )
.className { z-index: 99999 !important; }
correct example ( it work )
.className { position: 'relative'; z-index: 99999 !important; }
.className { position: 'absolute'; z-index: 99999 !important; }
etc..
good luck :)
so I am trying to create the effect seen on this website (for the photos on the left side of the column):
https://www.franshalsmuseum.nl/en/
I want to be able to change the image on scroll inside of a div.
And preferably, it won't scroll down past the page until all of the images have been scrolled through!
I'm trying to get the hang of javascript before adding things like jQuery, so can someone help with this using pureJS?`
window.onscroll = function() {
console.log(window.pageYOffset);
var img1 = document.getElementById('img1');
var img2 = document.getElemebtById('img2')
if ( window.pageYOffset > 1000 ) {
img1.classList.add("hidden");
img2.classList.remove("hidden");
} else {
img2.classList.add("hidden");
img1.classList.remove("hidden");
}
}
.rightPhotos {
max-width: 50%;
height: 50%;
overflow: auto;
}
.aPhoto {
max-height: 100%;
}
.hidden {
visibility: hidden;
}
.images {
width: 100%;
height: 100%;
}
<div class="other">
<div class="rightPhotos" onscroll="myFunction()">
<div class="aPhoto">
<img class ="images" id="img1" src="IMAGES/sunglasses.jpeg" alt="Woman with Sunglasses">
</div>
<div class="aPhoto hidden">
<img class="images" src="IMAGES/dancer1.jpg" alt="A Dancer">
</div>
</div>
</div>
`
The page you linked actually looks very nice, so I took a while to make something looking a bit closer to it than what other answers do.
I added a properly working transition, similar to one on franshalsmuseum.nl.
I styled the page to deal relatively well with being resized:
The sizing of panes and images is all ralative,
Scroll steps are relative to page height,
Images are shown using <div> with background-image instead of <img> tag. Depending on the size of the window, they are slightly cropped to adjust to changing aspect ratio of viewport.
I made the number of image sets very simple to change. It could be improved by creating the html elements in Javascript, but that doesn't look necessary. At least, it wouldn't be for the original page.
How it works
HTML
Images are put into special envelop elements (.img-wrapper), that provide proper sizing and positioning position: relative is important there). Each image element gets url (as background image url) and image set number to be used by javascript:
<div class="img visible" data-imageset="1"
style="background-image: url('http://placeimg.com/640/480/people');">
</div>
Class visible is set to show imageset 1 at the beginning.
CSS
The key points are these definitions (and similar for #bottom-image). As the element enveloping the image has overflow: hidden, we can hide the image by moving it outside of visible area. When we set coordinates back to normal, the image will slide back, using the smooth transition.
/* hiding images in #top-image */
#left-pane #top-image .img {
top: 100%;
}
#left-pane #top-image .img.visible {
top: 0;
}
JS
The Javascript code is very minimal, the interaction with DOM is really one line. However, it uses some tricks that may not be obvious, so there is this line with some links to documentation:
document.querySelectorAll('#left-pane .img').forEach((img) => {
img.classList.toggle('visible', img.dataset.imageset <= currentSet);
}
It just finds all images and adds or removes class visible depending on the data-imageset attribute of the image.
Full snippet with demo
See snippet below. Demo looks much better if you use "Full page" link after running the snippet.
let currentSet = 1;
function updateSelectedImgSet() {
const currentScroll = document.scrollingElement.scrollTop;
const scrollMax = document.scrollingElement.scrollHeight - document.scrollingElement.clientHeight;
const setsCount = 3;
const scrollPerSet = scrollMax / setsCount;
const scrolledSet = Math.floor(currentScroll / scrollPerSet) + 1;
if (scrolledSet == currentSet) {
return;
}
currentSet = scrolledSet;
document.querySelectorAll('#left-pane .img').forEach((img) => {
img.classList.toggle('visible', img.dataset.imageset <= currentSet);
});
}
window.onscroll = updateSelectedImgSet;
window.onresize = updateSelectedImgSet;
/* Left pane, fixed */
#left-pane {
position: fixed;
height: 100%;
width: 40vw;
}
#left-pane .img-wrapper {
position: relative;
height: 50%;
width: 100%;
overflow: hidden;
}
#left-pane .img-wrapper .img {
position: absolute;
width: 100%;
height: 100%;
/* Sizing and cropping of image */
background-position: center;
background-size: cover;
/* Transition - the slow sliding of images */
transition: 0.5s all ease-in-out;
}
/* hiding images in #top-image */
#left-pane #top-image .img {
top: 100%;
}
#left-pane #top-image .img.visible {
top: 0;
}
/* hiding images in #bottom-image */
#left-pane #bottom-image .img {
bottom: 100%;
}
#left-pane #bottom-image .img.visible {
bottom: 0;
}
/* Right pane, scrolling with the page */
#right-pane {
margin-left: 40vw;
}
.scrollable-content {
font-size: 40vw;
writing-mode: vertical-rl;
white-space: nowrap;
}
<div id="left-pane">
<div id="top-image" class="img-wrapper">
<div class="img visible" data-imageset="1"
style="background-image: url('http://placeimg.com/640/480/people');">
</div>
<div class="img" data-imageset="2"
style="background-image: url('http://placeimg.com/640/480/animals');">
</div>
<div class="img" data-imageset="3"
style="background-image: url('http://placeimg.com/640/480/any');">
</div>
</div>
<div id="bottom-image" class="img-wrapper">
<div class="img visible" data-imageset="1"
style="background-image: url('http://placeimg.com/640/480/nature');">
</div>
<div class="img" data-imageset="2"
style="background-image: url('http://placeimg.com/640/480/tech');">
</div>
<div class="img" data-imageset="3"
style="background-image: url('http://placeimg.com/640/480/arch');">
</div>
</div>
</div>
<div id="right-pane">
<div class="scrollable-content">Scrollable content!</div>
</div>
see code bellow:(I set 60 insteed 1000 (in function)for see changes)
I use one image and onscroll change the src of image
window.onscroll = function() {
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2')
if ( window.pageYOffset > 60 ) {
document.getElementById("img1").src = "https://material.angular.io/assets/img/examples/shiba2.jpg";
} else {
document.getElementById("img1").src = "https://material.angular.io/assets/img/examples/shiba1.jpg";
}
}
.rightPhotos
{
max-width: 50%;
height:50%;
overflow: auto;
}
.aPhoto
{
max-height: 100%;
}
.images
{
width: 100%;
height: 500px;
}
<div class="other">
<div class="rightPhotos" onscroll="myFunction()">
<div class="aPhoto">
<img class ="images" id="img1" src="https://material.angular.io/assets/img/examples/shiba1.jpg" alt="Woman with Sunglasses"/>
</div>
</div>
</div>
You can use the CSS properties to show/ hide the elements; instead of having custom CSS with hidden class.
if ( window.pageYOffset > 1000 ) {
img1.style.visibility = 'hidden';
img2.style.visibility = 'visible';
} else {
img2.style.visibility = 'hidden';
img1.style.visibility = 'visible';
}
The above would hide the element, but the DOM element would still occupy space.
For it now to have space occupied (like to remove it)
if ( window.pageYOffset > 1000 ) {
img1.style.display = 'none';
img2.style.display = 'block';
} else {
img1.style.display = 'block';
img2.style.display = 'none';
}
//window.pageYOffset
var scrollingDiv = document.getElementById('scrollContainer');
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2');
scrollingDiv.onscroll = function(event) {
if (scrollingDiv.scrollTop < 500) {
img1.src = "https://placeimg.com/250/100/arch";
img2.src = "https://placeimg.com/250/100/animals";
}
if (scrollingDiv.scrollTop > 500) {
img1.src = "https://placeimg.com/250/100/nature";
img2.src = "https://placeimg.com/250/100/people";
}
if (scrollingDiv.scrollTop > 1000) {
img1.src = "https://placeimg.com/250/100/tech";
img2.src = "https://placeimg.com/250/100/any";
}
}
.container{
display: table;
width: 100%;
height: 100%;
}
body{
margin: 0;
}
.container > div {
vertical-align:top;
}
.left, .middle, .right {
display: table-cell;
height: 100vh;
box-sizing: border-box;
}
.left, .right{
width:40%;
background: gray;
}
.middle{
overflow: auto;
position: relative;
}
.in-middle{
background: tomato;
position: absolute;
width: 100%;
height: 100%;
box-sizing: border-box;
margin: 0;
}
.in-in-middle{
height: 500px;
background: tomato;
}
.in-in-middle:nth-child(2){
background: pink;
}
.in-in-middle:nth-child(3){
background: skyblue;
}
.left img{
width: 100%;
transition: all 0.5s;
}
<div class="container">
<div class="left">
<img id="img1" src="https://placeimg.com/250/100/arch">
<img id="img2" src="https://placeimg.com/250/100/animals">
</div>
<div class="middle" id="scrollContainer">
<div class="in-middle">
<div class="in-in-middle" id="1"></div>
<div class="in-in-middle" id="2"></div>
<div class="in-in-middle" id="3"></div>
</div>
</div>
</div>
CodePen of the nav
On the first interaction with the mobile nav, it will open and close as expected but anything after that and there's a bug. It will begin to open and close instantly or the links will appear is weird orders.
What I need is for the mobile nav to first open from right to left, have each of the links to cascade into the view, starting from About all the way to Blog, and then I would like it to reverse when leaving the view.
Right now I don't have the logic implemented for the reverse but I need to work out this bug before I get to that.
SNIPPET
const bars = document.querySelector('.fa-bars');
bars.addEventListener('click', () => {
const navItemsContainer = document.querySelector('.navbar__links-container');
const navItems = document.querySelectorAll('.navbar__links-container__item');
const sleep = ms => {
return new Promise(resolve => {
setTimeout(() => {
return resolve();
}, ms);
});
};
const startNavAnimation = async () => {
let count = 0;
for (let item of navItems) {
if (item.classList.contains('navbar__links-container__item--show')) {
setTimeout(() => {
item.style.transitionDelay = `${ count }s`
item.classList.remove('navbar__links-container__item--show');
count += .15;
}, count);
}
else {
item.style.transitionDelay = `${ count }s`
item.classList.add('navbar__links-container__item--show');
count += .15;
}
}
};
if (navItemsContainer.classList.contains('navbar__links-container--open')) {
navItems[ navItems.length - 1 ].addEventListener('transitionend', () => {
navItemsContainer.classList.remove('navbar__links-container--open');
});
}
else {
navItemsContainer.classList.add('navbar__links-container--open');
}
startNavAnimation();
});
body {
margin: 0;
}
.navbar {
background: #f2f2f2;
display: flex;
flex-wrap: wrap;
}
.navbar__mobile-container {
display: flex;
justify-content: space-around;
width: 100%;
}
.fa-bars {
cursor: pointer;
}
.navbar__links-container {
background: inherit;
display: flex;
flex-direction: column;
align-items: flex-end;
list-style: none;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
top: 20px;
left: 100%;
transition: left .25s, width .25s;
width: 0%;
}
.navbar__links-container__item {
left: 52px;
margin-bottom: 1rem;
position: relative;
transition: left .25s;
width: auto;
}
.navbar__links-container--open {
left: 0;
width: 100%;
}
.navbar__links-container__item--show {
left: -63px;
}
<nav class="navbar">
<div class="navbar__mobile-container">
<div class="navbar__logo-container">
<a class="navbar__logo-container__logo">BB</a>
</div>
<div class="navbar__hamburger-container">
<i class="fas fa-bars">MENU</i>
</div>
</div>
<ul class="navbar__links-container">
<li class="navbar__links-container__item">
<a class="navbar__links-container__item__link">About</a>
</li>
<li class="navbar__links-container__item">
<a class="navbar__links-container__item__link">Portfolio</a>
</li>
<li class="navbar__links-container__item">
<a class="navbar__links-container__item__link">Blog</a>
</li>
</ul>
</nav>
NOTES
I think the problem is the first if statement in the bars event-handler. Something about the way it's waiting for the transitionend event but the startNavAnimation hasn't been called.
There are two issues.
One is that you are adding a new event listener inside of the click event listener. I moved that outside.
The second issue is that the --open class is going to be there while the menu is opening or closing so you need another way to test open or closed status. To make the Codepen clear to understand, I just used an isOpen flag.
https://codepen.io/Jason_B/pen/jzGwQX?editors=0010
I like using classes for this, and your code shows that you do too, so you might want to have a class for open status and a class for visibility.
So, I am doing an assignment for my high school web design class, and I am having trouble getting the z-index of an image to change. There is supposed to be 2 images on top of each other. When you click the button on the page, the image on bottom will come to the top (or the top image will go to the bottom). Here is my code that I`m using:
The javascript
<script type="text/javascript">
function Switch()
{
document.getElementById("mononoke2").style.zIndex = "-1";
}
And here is the HTML
<div id="mononoke2">
<img src="mononoke2.png" alt="ashandsan">
</div>
<div id="mononoke3">
<img src="mononoke3.jpg" alt="sanandmoro" width="1234" height="694">
</div>
<button type="button" onclick="Switch()">Flippity Flip</button>
And the CSS
#mononoke2 {
margin-left: 0px auto;
margin-right: 0px auto;
display: block;
position: absolute;
z-index: 100;
}
#mononoke3 {
margin-left: 0px auto;
margin-right: 0px auto;
display: block;
position: relative;
left: 50px;
z-index: 20;
}
use jQuery.
$("#id").css("zindex","-1");
Change your JS function to this:
function Switch() {
var element = document.getElementById("mononoke2");
var style = window.getComputedStyle(element);
var index = style.getPropertyValue("z-index");
if(index > 0)
{
document.getElementById("mononoke2").style.zIndex = "-30";
}
else
{
document.getElementById("mononoke2").style.zIndex = "100";
}
}