I want to make another image change when I click on an image. The change is working. But it doesn't show me which is active for the small "clickimage".
CodePen: https://codepen.io/timbos/pen/vYjBZqz
Please help me with this.
.container{
display:flex;
flex-wrap:wrap;
gap:30px;
justify-content: center;
margin-top: 20px;"
}
.img-responsive{
max-width:100%;
}
.activeclick {
filter: grayscale(0%)!important;
}
.clickimage {
filter: grayscale(100%);
cursor:pointer;
width: 195px;
height: 61px;
background-size: contain;
}
<div style="max-width: 1024px;">
<img class="img-responsive" id="Images" src="https://abload.de/img/15iiid.jpg" />
<div class="container">
<div class="clickimage activeclick " onclick="changeImage('https://abload.de/img/15iiid.jpg')" style=" background-image: url(https://abload.de/img/click1d0f8r.jpg); ">
</div>
<div class="clickimage" onclick="changeImage('https://abload.de/img/289ejs.jpg')" style="background-image: url(https://abload.de/img/click2bwddr.jpg);">
</div>
<div class="clickimage" onclick="changeImage('https://abload.de/img/33dfif.jpg')" style=" background-image: url(https://abload.de/img/click3q0ik5.jpg);
">
</div>
</div>
</div>
<script>
function changeImage(fileName){
let img = document.querySelector("#Images");
img.setAttribute("src", fileName);
var elems = document.querySelectorAll("activeclick ");
[].forEach.call(elems, function(el) {
el.classList.remove("activeclick");
});
e.target.className = "activeclick";
}
</script>
function "changeImage" has second parameter "this" (added also into HTML onclick for target identification in function)
var elems = document.querySelectorAll(".activeclick"); (there was missing dot for classname)
e.target.className = "activeclick"; was changed to e.classList.add("activeclick"); (better syntax for classname addition)
.container{
display:flex;
flex-wrap:wrap;
gap:30px;
justify-content: center;
margin-top: 20px;"
}
.img-responsive{
max-width:100%;
}
.activeclick {
filter: grayscale(0%)!important;
}
.clickimage {
filter: grayscale(100%);
cursor:pointer;
width: 195px;
height: 61px;
background-size: contain;
}
<div style="max-width: 1024px;">
<img class="img-responsive" id="Images" src="https://abload.de/img/15iiid.jpg" />
<div class="container">
<div class="clickimage activeclick " onclick="changeImage('https://abload.de/img/15iiid.jpg', this)" style=" background-image: url(https://abload.de/img/click1d0f8r.jpg); ">
</div>
<div class="clickimage" onclick="changeImage('https://abload.de/img/289ejs.jpg', this)" style="background-image: url(https://abload.de/img/click2bwddr.jpg);">
</div>
<div class="clickimage" onclick="changeImage('https://abload.de/img/33dfif.jpg', this)" style=" background-image: url(https://abload.de/img/click3q0ik5.jpg);
">
</div>
</div>
</div>
<script>
function changeImage(fileName, e){
let img = document.querySelector("#Images");
img.setAttribute("src", fileName);
var elems = document.querySelectorAll(".activeclick");
[].forEach.call(elems, function(el) {
el.classList.remove("activeclick");
});
e.classList.add("activeclick");
}
</script>
.container{
display:flex;
flex-wrap:wrap;
gap:30px;
justify-content: center;
margin-top: 20px;"
}
.img-responsive{
max-width:100%;
}
.activeclick {
filter: grayscale(0%)!important;
}
.clickimage {
filter: grayscale(100%);
cursor:pointer;
width: 195px;
height: 61px;
background-size: contain;
}
<div style="max-width: 1024px;">
<img class="img-responsive" id="Images" src="https://abload.de/img/15iiid.jpg" />
<div class="container">
<div class="clickimage activeclick " onclick="changeImage(event,'https://abload.de/img/15iiid.jpg')" style=" background-image: url(https://abload.de/img/click1d0f8r.jpg); ">
</div>
<div class="clickimage" onclick="changeImage(event,'https://abload.de/img/289ejs.jpg')" style="background-image: url(https://abload.de/img/click2bwddr.jpg);">
</div>
<div class="clickimage" onclick="changeImage(event,'https://abload.de/img/33dfif.jpg')" style=" background-image: url(https://abload.de/img/click3q0ik5.jpg);
">
</div>
</div>
</div>
<script>
function changeImage(event,fileName){
let img = document.querySelector("#Images");
img.setAttribute("src", fileName);
var elems = document.querySelectorAll("activeclick ");
[].forEach.call(elems, function(el) {
el.classList.remove("activeclick");
});
event.target.classList.add("activeclick");
}
</script>
Like this it should work.
It is mostly cause e was not defined and you have to pass the event to the function manually. If you use it like this.
But I highly reccommend declaring eventlisteners through js and not defining them in the html.
I've reworked your HTML so that it doesn't use inline onclick attributes. Please don't use them as they are part of an old JS spec; we have many better alternatives, like addEventListener. Even browser vendors advice to use against them - source.
Also using [].forEach.call comes from a time where browser support for the forEach method on a NodeList was shotty. Looping just became easier with for...of.
Every function that is used as a callback for an event - for examle with addEventListener - exposes an Event object. You forgot to expose the parameter which makes it difficult to know which button was pressed.
const img = document.querySelector("#Images");
const buttons = document.querySelectorAll('.clickimage');
for (const button of buttons) {
button.addEventListener('click', changeImage);
}
function changeImage(event) {
event.preventDefault();
const fileName = event.target.value;
img.src = fileName;
for (const button of buttons) {
button.classList.remove('activeclick');
}
event.target.classList.add('activeclick');
}
.container {
display: flex;
flex-wrap: wrap;
gap: 30px;
justify-content: center;
margin-top: 20px;
}
.img-responsive {
max-width: 100%;
}
.activeclick {
filter: grayscale(0%)!important;
}
.clickimage {
filter: grayscale(100%);
cursor: pointer;
width: 195px;
height: 61px;
background-size: contain;
}
<div style="max-width: 1024px;">
<img class="img-responsive" id="Images" src="https://abload.de/img/15iiid.jpg" />
<div class="container">
<button class="clickimage activeclick " value="https://abload.de/img/15iiid.jpg" style=" background-image: url(https://abload.de/img/click1d0f8r.jpg); "></button>
<button class="clickimage" value="https://abload.de/img/289ejs.jpg" style="background-image: url(https://abload.de/img/click2bwddr.jpg);"></button>
<button class="clickimage" value="https://abload.de/img/33dfif.jpg" style=" background-image: url(https://abload.de/img/click3q0ik5.jpg);
"></button>
</div>
</div>
You have to pass event to function, something like this
<element onclick="changeImage('https://abload.de/img/33dfif.jpg', event)" ...
and in your function, change parameters to this
function changeImage(fileName, e) {
so you get two parameters, filename and event
Instead of html click Event, you should use js events with addEventListener (then you can storage your new image in a data attribute).
You should use getElementById instead of querySelector :
getElementById() can run about 15 million operations a second, compared to just 7 million per second for querySelector() in the latest version of Chrome. (Source, Pen I found)
Same for getElementsByClassName instead of querySelectorAll.
You only have one .activelink so you can select if with querySelector(".activeclick") or getElementsByClassName("activeclick")[0] (I'm not sure wich one is the best).
If you use for exemple addEventListener("click", (el) => {}), you can add your class with el.classList.add("activeclick").
I guess it's for the example, but in case you use images as simple as that, you could remake them with css
for (let e of document.getElementsByClassName("button")) {
e.addEventListener("click", () => {
document.querySelector(".selected").classList.remove("selected")
e.classList.add("selected")
})
}
.container{
counter-reset: section;
display:flex;
flex-wrap:wrap;
gap:30px;
justify-content: center;
margin-top: 20px;"
}
.button{
background-color:#bdbdbd;
cursor:pointer;
width: 195px;
height: 61px;
font-weight: bold;
font-size:20px;
display: flex;
justify-content: center;
align-items: center;
}
.button:before{
content:"Click\00a0";
}
.button:after{
counter-increment: section;
content: counter(section);
}
.selected{
background-color:#A3C2D6;
}
<div class="container">
<div class="button selected"></div>
<div class="button"></div>
<div class="button"></div>
</div>
Related
I am working on an assignment with the description of:
Create a JavaScript loop using images to get the output as picture below. You can use any images and it is requiring to use maximum 5 images. The images should be loop infinitely. Use your own creativity to design the layout.
But I have no idea how to work on that, I only created a div with three images in it and stuck on the javascript part.
This is my code:
.container {
width: 100%;
height: 27vh;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.box {
width: 200px;
height: 200px;
margin: 1px;
}
img {
width: 200px;
height: 200px;
}
<div class="container">
<div class="box">
<img class="car" src="images/car1.jpg">
</div>
<div class="box">
<img class="car" src="images/car2.jpg">
</div>
<div class="box">
<img class="car" src="images/car3.jpg">
</div>
</div>
This is what I've got now:
Here is something to get you started. I changed <div class="container"> to <div id="container"> and added another container within that one: .box-container.
The basic idea is to clone a container with the initial images, and then append (add) them to your original container.
let numberOfRows = 3;
const containerDiv = document.getElementById('container');
// get first element in #container, which is just one child: .box-container
let boxContainerDiv = containerDiv.children[0];
while (numberOfRows) {
numberOfRows--;
// clone the node
let clonedChild = boxContainerDiv.cloneNode(true);
// add the clone node to #container
containerDiv.appendChild(clonedChild);
}
.box-container {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.box {
width: 200px;
height: 200px;
margin: 1px;
}
img {
width: 200px;
height: 200px;
border: 1px solid;
}
<div id="container">
<div class="box-container">
<div class="box">
<img class="car" src="https://via.placeholder.com/200.png?text=1">
</div>
<div class="box">
<img class="car" src="https://via.placeholder.com/200.png?text=2">
</div>
<div class="box">
<img class="car" src="https://via.placeholder.com/200.png?text=3">
</div>
</div>
</div>
I am working on my own website and not good with codes yet. When I am scrolling down I want to appear another content of the navbar and when I am on the top, original navbar is appearing. I want this to be done in pure JavaScript with no libraries or framewokrs. Please see codes below and I know that codes are not organised. I will do that later on.
var nav = document.querySelector("nav");
var hide = document.querySelector(".hide");
var appear = document.querySelector(".appear")
window.onscroll = function(){
if(document.body.scrollTop > 70){
hide.style.display = "block";
appear.style.display = "none"
} else {
hide.style.display = "none";
appear.style.display = "block"
}
}
nav{
list-style-type: none;
text-align: center;
background-color: #3FA9A5;
position: sticky;
top: 0;
}
.hide{
font-size: 70px;
font-family: 'Long Cang', cursive;
display: block;
}
.appear{
height: 70px;
display: none;
}
.appear img{
width: 210px;
}
ul{
margin: 0 auto;
padding: 0;
}
body{
margin: 0;
}
.container{
max-width: 1080px;
width: 95%;
margin: 10px auto;
display: grid;
grid-template-columns: 25% 50% 25%;
}
.text{
text-align: center;
}
.profile {
border: 1px solid black;
padding: 0 10px 20px 10px;
}
#main{
width: 100%;
}
.post{
margin-left: 4.165%;
}
#image{
width: 100%;
}
#post-divide{
margin-left: 10px;
margin-right: 10px;
}
.comments{
width: 100%;
margin-top: 68.5px;
padding-bottom: 293.5px;
border: 1px solid black;
}
h2{
text-align: center;
}
.center{
grid-column: 2;
}
<link rel="stylesheet" type="text/css" href="test.css">
<link href="https://fonts.googleapis.com/css?family=Indie+Flower|Long+Cang&display=swap" rel="stylesheet">
<title>test</title>
</head>
<body>
<nav>
<ul>
<li class="hide">Unknown</li>
<li class="appear"><img src="cat.png"></li>
</ul>
</nav>
<div class="container">
<div class="col-1">
<div class="profile text">
<img id="main" src="https://data.whicdn.com/images/86629641/superthumb.jpg?t=1384568664">
<hr>
<p>12 posts</p>
<p>instagram</p>
<button>Subscribe!</button>
</div>
</div>
<div class="col-1">
<div class="post">
<h2>TITLE</h2>
<div>
<img id="image" src="https://i.pinimg.com/originals/76/d4/8c/76d48cb2928845dfcfab697ac7cbcf1c.jpg">
</div>
<hr id="post-divide">
</div>
</div>
<div class="col-1">
<div class="comments text"></div>
</div>
<div class="col-1 center">
<div class="post">
<h2>TITLE</h2>
<div>
<img id="image" src="https://i.pinimg.com/originals/76/d4/8c/76d48cb2928845dfcfab697ac7cbcf1c.jpg">
</div>
<hr id="post-divide">
</div>
</div>
<div class="col-1">
<div class="comments text"></div>
</div>
</div>
I think I should add something to the JS code but don't know why
Would be thankful if you would advise me how could I write HTML/CSS code so I do not have to create 2 navbars if it is possible
The following instruction:
document.querySelector("hide");
Will query for elements like:
<hide></hide>
Since plain selectors without prefix (div, header, span) will query for the whole element tags, not for classes or attrbitues.
Maybe you meant to query for the class, using the .:
document.querySelector(".hide");
var hide = document.querySelector(".hide");
var appear = document.querySelector(".appear")
So you should use class selector
You are using "hide" and "appear" as selectors but they do not exist in your HTML.
Use ".hide" and ".appear" in your querySelector instead.
var hide = document.querySelector(".hide");
var appear = document.querySelector(".appear");
Since both navbars have a static data, I would suggest to keep both of them and follow with answers of guys, that suggested to update querySelector param. Or you can hide/show the data inside of navbar (in your case it's only ul element) and leave the whole navbar always visible. So you can put classes appear/hide on ul element instea of navbar and then in JS get them with document.querySelector('.navbar .hide') and document.querySelector('.navbar .appear').
Using framework/library will definitely simplify it.
However, if you still want to have only one navbar in pure js/html/css (or it's data just dynamic) I would probably do like this:
HTML:
<nav class="navbar">
<ul>
<li><img src="cat.png"></li>
</ul>
</nav>
somewhere in JS:
var navbarUl = document.querySelector('.navbar ul');
window.onscroll = function() {
if (document.body.scrollTop > 70) {
navbarUl.innerHtml = '';
navbarUl.appendChild(getTopNavbarHTML);
} else {
navbarUl.innerHtml = '';
navbarUl.appendChild(getNavbarHTML);
}
}
getNavbarHTML and getTopNavbarHTML - will return documentFragment with li elements, see for details https://www.w3schools.com/jsref/met_document_createdocumentfragment.asp
But changing DOM during a scroll event can drastically decrease performance of a web app
I am using node.js with the handlebars template engine. Currently, the thumbnail images from the database are displaying at a width and height of 70 which is specified in the code. See below. How can I allow the user to click on the image in handlebars and see a larger rendition of the photo?
The current images are too small to see but I would only like for them to be increased upon clicking them.
I am using handlebars....so a variation of this would help...(without "onClick=" method as I am using node.js and it won't work)
<style>
img.std {
height: 10%;
}
img.big {
height: 40%;
}
</style>
<img id="img" class="std" onClick="(this.className=='std')?this.className='big':this.className='std'" src="/uploads/{{photo_image}}">
You can add an IIFE type function, and use an arrow function so the this keyword refers to the image:
.container{
height: 200px;
border: solid 1px gray;
}
img.std {
height: 60%;
}
img.big {
height: 80%;
}
<div class="container">
<img id="img" class="std" onClick="(() => {
this.className = this.className === 'std' ? 'big' : 'std';
})(); return false;" src="http://placekitten.com/200/200">
</div>
You can do this quite easily with jQuery with:
$(document).on('click','img',function(){
if (this.id == "img") {
this.className=='std' ? this.className = 'big' : this.className='std';
}
});
<img id="img" class="std" src="/uploads/{{photo_image}}">
I would suggest to use unique id for the tag to avoid future ambiguity (potential bugs).
Here's the checkbox hack implemented to your code:
.imgcontainer {
position: relative;
display: inline-flex;
align-items: stretch;
justify-content: stretch;
}
.imgcontainer input[type='radio'] {
opacity: 0;
position: absolute;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.imgcontainer input[type='radio'] + img.std {
height: auto;
width: 100px;
}
.imgcontainer input[type='radio']:checked + img.std {
width: 200px;
}
<div class="imgcontainer">
<input type="radio" name="imgcontainerradio">
<img id="img" class="std" src="http://placeimg.com/640/480/any">
</div>
<div class="imgcontainer">
<input type="radio" name="imgcontainerradio">
<img id="img" class="std" src="http://placeimg.com/640/480/arch">
</div>
<div class="imgcontainer">
<input type="radio" name="imgcontainerradio">
<img id="img" class="std" src="http://placeimg.com/640/480/nature">
</div>
What I'm trying to do:
1 - How can I use a second file input to set the background image of a class of divs, in this case the class .logo? (currently, I have one file input, which is setting the background image for the class .background, but I need to add a second file input)
2 - How can I include a link that will "delete" or "trash" the file selected via the file input in order to reset a class of divs as having no background image?
Here is how I've tried to work through this problem so far:
I tried to add a second button, and duplicate the JS and then change the class names, however this broke everything. So I've provided two buttons for the file inputs here. Also, I tried to search for how to delete a file input once uploaded, but I could not understand anything I found. I read through this question about clearing a form, but I could not successfully apply what was described.
Here's what I've tried so far:
$('.verborgen_file').hide();
$('.uploadButton').on('click', function() {
$('.verborgen_file').click();
});
$('.verborgen_file').change(function() {
var file = this.files[0];
var reader = new FileReader();
reader.onloadend = function() {
$('.background').css('background-image', 'url("' + reader.result + '")');
}
if (file) {
reader.readAsDataURL(file);
} else {}
});
.background {
background-image: url("");
background-position: center;
width: 100%;
border: 0px dashed #ddd;
background-color: #fbfbfb;
padding: 10px;
}
.background:hover {
cursor: move;
}
div.bg-img {
background-position: center;
background-repeat: no-repeat;
}
.responsive {
background-image: url("");
background-size: 120%;
background-position: center;
min-height: 20vh;
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
position: relative;
}
.medium {
background-image: url("");
background-size: cover;
background-position: center;
height: 150px;
width: 100%;
margin-top: 15px;
margin-bottom: 15px;
position: relative;
}
.logo {
height: 50px;
width: 80px;
background-color: #eee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="inputSection">
<h1>Input Section</h1>
Background:
<input type='file' class='verborgen_file' />
<input type="button" value="Upload" class="uploadButton" />
delete
<br> Logo:
<input type="button" value="Upload" class="uploadButton" />delete
</div>
<br>
<div class="imageSection">
<h1>Divs with Images Section</h1>
<div class="background responsive bg-img">
<div class="logo">
</div>
</div>
<div class="background medium bg-img">
<div class="logo">
</div>
</div>
</div>
In my experience, I would suggest to put the files that being selected by input in an array for further works.
But in your case, it would be simple. (However, the HTML structure makes this problem a little more complex.)
I added some input in HTML and added some data-attribute to <input> and <a>.
And, see comments below...
Edit: Since you separated them and put into another div, the parent() would be that div. Our goal is looking for the div contains both inputSection and imageSection, so replace parent() with parents('.container'). That's it!
$('.verborgen_file').hide();
$('.uploadButton').on('click', function() {
// find relative input and trigger click event
var id = $(this).data('id')
var target = $(this).siblings('input[data-id=' + id + ']')
target.click();
});
$('.verborgen_file').change(function() {
var $this = $(this)
var file = this.files[0];
var id = $(this).data('id')
var reader = new FileReader();
reader.onload = function() {
// find either .background or .logo class in container and change the image
$('body').find('div[data-id='+ id +']').css('background-image', 'url("' + reader.result + '")');
}
if (file) {
reader.readAsDataURL(file);
} else {
// if file doesn't exist, clear the image
$('body').find('div[data-id='+ id +']').css('background-image', '');
}
});
$('a').on('click', function(e) {
e.preventDefault()
var $this = $(this)
var id = $this.data('id')
var inputID = $this.siblings('input[data-id=' + id + ']').attr('id')
// clear the relative input and trigger change event
$('#' + inputID).val('').trigger('change')
})
.background {
background-image: url("");
background-position: center;
width: 100%;
border: 0px dashed #ddd;
background-color: #fbfbfb;
padding: 10px;
}
.background:hover {
cursor: move;
}
div.bg-img {
background-position: center;
background-repeat: no-repeat;
}
.responsive {
background-image: url("");
background-size: 120%;
background-position: center;
min-height: 20vh;
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
position: relative;
}
.medium {
background-image: url("");
background-size: cover;
background-position: center;
height: 150px;
width: 100%;
margin-top: 15px;
margin-bottom: 15px;
position: relative;
}
.logo {
height: 50px;
width: 80px;
background-color: #eee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<h1>Input Section</h1>
<div class="inputSection">
Background:
<input id="bgInput1" type='file' class='verborgen_file' data-id="background1" />
<input type="button" value="Upload" class="uploadButton" data-id="background1" />
delete
<br> Logo:
<input id="logoInput1" type='file' class='verborgen_file' data-id="logo1" />
<input type="button" value="Upload" class="uploadButton" data-id="logo1" />
delete
</div>
<br>
<div class="imageSection">
<h1>Divs with Images Section</h1>
<div class="background responsive bg-img" data-id="background1">
<div class="logo" data-id="logo1">
</div>
</div>
<div class="background medium bg-img" data-id="background1">
<div class="logo" data-id="logo1">
</div>
</div>
</div>
</div>
<div class="container">
<h1>Input Section</h1>
<div class="inputSection">
Background:
<input id="bgInput2" type='file' class='verborgen_file' data-id="background2" />
<input type="button" value="Upload" class="uploadButton" data-id="background2" />
delete
<br> Logo:
<input id="logoInput2" type='file' class='verborgen_file' data-id="logo2" />
<input type="button" value="Upload" class="uploadButton" data-id="logo2" />
delete
</div>
<br>
<div class="imageSection">
<h1>Divs with Images Section</h1>
<div class="background responsive bg-img" data-id="background2">
<div class="logo" data-id="logo2">
</div>
</div>
<div class="background medium bg-img" data-id="background2">
<div class="logo" data-id="logo2">
</div>
</div>
</div>
</div>
This is a followup to my earlier question, Fade in/out js mouseover event.
I am looking to incorporate a div mouseover effect on a small menu on my page. My previous question solved the issue, but I had not incorporated the page layout into the function, which has now stopped it from working.
My basic code is:
<style type="text/css">
.hidden{
display:none;
}
#container {
margin: 0%;
padding: 0;
width: 100%;
background-color: #222222;
}
#left, #right {
float: left;
margin: 0% 0 0% 0%;
padding: 0%;
background-color: #000;
}
#right {
float: right;
margin: 0% 0% 0% 0;
}
.clear {
height: 0;
font-size: 1px;
margin: 0;
padding: 0;
line-height: 0;
clear: both;
}
</style>
<script type="text/javascript">
oldSelected = "home"
$ (document).ready(function(){
$ ("#products img").mouseover(function(){
$ (".description").stop(true, true);
var newSelected = $(this).attr("alt");
$ ("#" + oldSelected).fadeOut('normal',function(){
$ ("#" + newSelected).fadeIn();
});
oldSelected = newSelected
});
});
</script>
<body>
<div id="container" style="width: 974px; height: 200px;">
<div id="left" style="width: 200px; height: 200px;">
<div id="products" >
<img src="home.png" alt="home" />
<img src="services.png" alt="services" />
<img src="contact.png" alt="contact" />
</div>
</div>
<div id="right" style="width: 760px; height: 200px;">
<div class="description" id="home">
.. content ..
</div>
<div class="description" id="services">
.. content ..
</div>
<div class="description" id="contact">
.. content ..
</div>
</div>
</div>
I assume the mouseover effect has stopped working due to the products and description divs being relocated under new divs.
How do I go about adjusting the code to get the function working again under this layout? Would it work in a table layout instead?
You can try .slideDown and .slideUp
or .show() .hide() with duration