I'm using this code to show img alt inside show div. The problem is that it doesn't update at every img change.
Is there any different addEventListener that I can use so that it will change the alt at every visible image on the screen and without the need to click?
var myImage = document.getElementsByTagName("img");
var text = document.getElementById("show");
for (var i = 0; i < myImage.length; i++) {
myImage[i].addEventListener('click',show);
}
function show(){
var myAlt = this.alt;
text.innerHTML = myAlt;
}
Thanks in advance.
Why not simply iterate over the images as soon as the HTML is ready? Simply attach a single listener to the DOMContentLoaded event:
document.addEventListener('DOMContentLoaded', () => {
let images = [...document.querySelectorAll('img[alt]')]
for (const image of images) {
const altDiv = document.createElement('div')
altDiv.textContent = image.getAttribute('alt')
image.parentNode.appendChild(altDiv)
}
})
<div>
<img src="http://lorempixel.com/200/200/" alt="my beautiful alt text" />
</div>
<div>
<img src="http://lorempixel.com/200/100/" alt="my beautiful alt text 2" />
</div>
If you want to make sure the images are loaded before showing the alt text, do the showText magic on the load event of each image:
document.addEventListener('DOMContentLoaded', () => {
let images = [...document.querySelectorAll('img[alt]')]
for (const image of images) {
image.addEventListener('load', (e) => {
const altDiv = document.createElement('div')
altDiv.textContent = image.getAttribute('alt')
image.parentNode.appendChild(altDiv)
})
}
})
<div>
<img src="http://lorempixel.com/200/200/" alt="my beautiful alt text" />
</div>
<div>
<img src="http://lorempixel.com/100/200/" alt="my beautiful alt text 2" />
</div>
<div>
<img src="http://lorempixel.com/200/100/" alt="my beautiful alt text 3" />
</div>
Related
I have a container with a total of 16 images of balloons. I want to remove each image when hovering over dem and replacing each with an image that says pop. When I remove the first image with "click" it works fine, but when I remove the second balloon image, the pop image that was appended first is removed, and so on. In my image folder, I have balloon images and pop images
html (only 4 images included here for simplicity):
<div class="row first-row">
<div class="col-3" id="red-div" >
<img class = "balloon" src="./images/balloon-red.png" id="red"/>
</div>
<div class="col-3" id="blue-div" >
<img class = "balloon" src="./images/balloon-blue.png" id="blue"/>
</div>
<div class="col-3" id="pink-div" >
<img class = "balloon" src="./images/balloon-pink.png" id="pink"/>
</div>
<div class="col-3" id="white-div">
<img class = "balloon" src="./images/balloon-white.png" id="white"/>
</div>
</div>
</div>
<script>
const images = document.querySelectorAll("img");
console.log(images)
let popImage = document.createElement("img");
function removeImage(image) {
image.remove();
}
function appendImage(image) {
popImage.setAttribute("src", `./images/pop-${image.getAttribute("id")}.png`);
image.parentNode.appendChild(popImage);
}
images.forEach((image) => {
image.addEventListener(
"click", e=> {
appendImage(image);
if(image.className =="balloon"){
console.log(image.className)
removeImage(image);
// e.stopPropagation();
}
}
);
});
</script>
The problem is that you are moving popImage instead of creating a new one each time.
Simply move let popImage = document.createElement("img"); into appendImage() function:
const images = document.querySelectorAll("img");
console.log(images)
function removeImage(image) {
image.remove();
}
function appendImage(image) {
let popImage = document.createElement("img");
popImage.setAttribute("src", `https://lh3.googleusercontent.com/9pPCK70Rw0k3wethMHb1qMaIB0VjeWLy57vYgSzKbF7oJuvO2nA0Nakk-95cvibWUDcEhYkfCKvdPKT03tXZd4M5jdhIEibLO9qw-XE=w1024-h683-n-l50-sg-rj
`);
image.parentNode.appendChild(popImage);
}
images.forEach((image) => {
image.addEventListener(
"click", e=> {
appendImage(image);
if(image.className =="balloon"){
console.log(image.className)
removeImage(image);
// e.stopPropagation();
}
}
);
});
img
{
width: 100px;
}
<div class="row first-row">
<div class="col-3" id="red-div" >
<img class = "balloon" src="https://lh3.googleusercontent.com/taykG37GWDgY-FGkdogDvsHSJMUGRMvkuVRT6yR-5UNkKvGRKeRlpGYXlslocOcS0txlfUdGW59JGtzADknxbMqnh6AtVCv9EXyB8nHp80YsRNA0Yw=w1024-h683-n-l50-sg-rj" id="red"/>
</div>
<div class="col-3" id="blue-div" >
<img class = "balloon" src="https://lh3.googleusercontent.com/IlhDxQVsR17dwwER5xYZJej867KrdSx0K5eyRP2RFP4eQJMD2pi0ZGBhrMOcajBUP9M54lpmIr90JecPUFGPaRe3sDZ82RvHBSw1rw-YJvQs7J8K3g=w1024-h683-n-l50-sg-rj" id="blue"/>
</div>
<div class="col-3" id="pink-div" >
<img class = "balloon" src="https://lh3.googleusercontent.com/aS2Up3osDMLTua1vXPTqnXko13KbIAmB0nQ44AP_IFTEt-VjUa6Tz2MC9jdH11bsZfjdiR8z4HbnxvhmmxSU1swKrtjc5PXreP6i=w1024-h683-n-l50-sg-rj" id="pink"/>
</div>
<div class="col-3" id="white-div">
<img class = "balloon" src="https://lh3.googleusercontent.com/fl-GT6w3Ls6RT4vYnbkuYUyLY3lZJH8VtZ7xzxiym9YYaoVRCnZehdz6Icd0oAf6i3H9-O5cCNs6eunlxWr_Csstgsb98DdzNdLFBOlhw9NUfHdyuQjI=w768-h1024-n-l50-sg-rj" id="white"/>
</div>
</div>
</div>
However, unless there is a good reason for removal of the original img element, a better approach would be simply replace src instead.
I Hope you can help me.
When I click button it adds night before file extension ex.(interior-1.jpg to interior-1-night) but it only affects the first image which is interior-1.jpg.
What I want is to add "night" text before the file extension of all images under the "image" ID.
Here is my html code
<button onclick="changeMode()">switch</button>
<img id="image" src="interior-1.jpg"/>
<img id="image" src="interior-2.jpg"/>
<img id="image" src="interior-3.jpg"/>
<img id="image" src="interior-4.jpg"/>
<img id="image" src="interior-5.jpg"/>
Here is my javascript code
<script>
function changeMode() {
var filename = document.getElementById("image").src;
var modfilename = filename.replace(/(\.[\w\d_-]+)$/i, '-night$1');
document.getElementById("image").src = modfilename;
</script>
}
You should never use same id name on elements in the dom. Instead use same class name. To apply the src on all the img tag get all the tags using document.getElementsByClassName. Iterate over each element and change the src using a forEach loop
function changeMode() {
var filename = document.getElementsByClassName("image");
var a = '';
Object.values(filename).forEach((e) => {
a = e.src;
var modfilename = a.replace(/(\.[\w\d_-]+)$/i, '-night$1');
e.src = modfilename;
})
}
<button onclick="changeMode()">switch</button>
<img class="image" src="interior-1.jpg" />
<img class="image" src="interior-2.jpg" />
<img class="image" src="interior-3.jpg" />
<img class="image" src="interior-4.jpg" />
<img class="image" src="interior-5.jpg" />
The problem is that you are getting your element by GetElementById which only returns one element. You should change the id tag to name like this:
<img name="image" src="interior-1.jpg"/>
Then you should be able to retrieve all the elements using var els = document.getElementsByName('image');
now you need to change their file names, so
for (let i = 0; i<els.length; i++){
els[i].src = els[i].src.replace(/(\.[\w\d_-]+)$/i, '-night$1');
}
Here is my two cents. Use classes. This way you can query multiple elements instead of just one. Then apply your changes to each element using, in this case, a forEach.
The elements returend from document.querySelectorAll is a nodeList. That's why I use Array.prototype.forEach.call.
function changeMode() {
const imageNodes = document.querySelectorAll(".image");
Array.prototype.forEach.call(imageNodes, (node) => {
let modfilename = node.src.replace(/(\.[\w\d_-]+)$/i, '-night$1');
node.src = modfilename
})
}
<button onclick="changeMode()">switch</button>
<img class="image" src="interior-1.jpg"/>
<img class="image" src="interior-2.jpg"/>
<img class="image" src="interior-3.jpg"/>
<img class="image" src="interior-4.jpg"/>
<img class="image" src="interior-5.jpg"/>
I am trying to change the img src based on what button I have clicked.
My current approach is to add event listeners to each img id and change then change the image of the top img tag. The issue with this apporach is that I will have a lot of repetetive code especially when im adding more buttons.
So i would like someone to give advice or show me a different and better approach to do this. Im requesting help in only native javascript. Thanks.
document.getElementById("human").addEventListener("click", e => {
document.getElementById('imageChange').src = "dir/images/human.png";
})
document.getElementById("dwarf").addEventListener("click", e => {
document.getElementById('imageChange').src = "dir/images/dwarf.png";
})
document.getElementById("elf").addEventListener("click", e => {
document.getElementById('imageChange').src = "dir/images/elf.png";
})
<img id="imageChange" src="dir/images/human.png" alt="">
<div class="buttonContainer">
<img src="../dir/images/race/human_male.png" id="human" class="race human_container"></img>
<img src="../dir/images/race/dwarf_male.png" id="dwarf" class="race dwarf_container"></img>
<img src="../dir/images/race/elf_male.png" id="elf" class="race elf_container"></img>
</div>
You are right, that having multiple event handler is not a good solution. You can have single one attached to the common container. Something like this:
document.querySelector(".buttonContainer").addEventListener("click", e => {
if (e.target.tagName === 'IMG') {
document.getElementById('imageChange').src = e.target.src
}
})
.buttonContainer img {
height: 30px;
width: 30px;
}
<img id="imageChange" src="https://cdn2.iconfinder.com/data/icons/oxygen/64x64/mimetypes/unknown.png" alt="">
<div class="buttonContainer">
<img src="https://cdn0.iconfinder.com/data/icons/social-network-7/50/4-64.png" id="human" class="race human_container" />
<img src="https://cdn0.iconfinder.com/data/icons/social-network-7/50/6-64.png" id="dwarf" class="race dwarf_container" />
<img src="https://cdn0.iconfinder.com/data/icons/social-network-7/50/29-64.png" id="elf" class="race elf_container" />
</div>
It is necessary to check event target e.target.tagName === 'IMG' because click event bound like this might get triggered by clicking on elements other than images (so with no src).
Since you already know what you want to change the image to why not add it in the html as a data- attribute then just replace the current src with the data- value?
var clickables = document.querySelectorAll('.race');
function showImage(e) {
var src = e.target.src;
document.getElementById('imageChange').src = src;
}
for (var i = clickables.length - 1; i >= 0; i--) {
clickables[i].addEventListener('click', showImage);
}
.buttonContainer img {max-width: 100px}
<img id="imageChange" src="https://upload.wikimedia.org/wikipedia/en/e/ed/Nyan_cat_250px_frame.PNG" alt=""/>
<div class="buttonContainer">
<img src="https://vignette.wikia.nocookie.net/nyancat/images/f/ff/Mexinyan.gif/revision/latest?cb=20150409011153" id="human" class="race human_container"/>
<img src="http://www.nyan.cat/cats/original.gif" id="dwarf" class="race dwarf_container"/>
<img src="https://upload.wikimedia.org/wikipedia/en/e/ed/Nyan_cat_250px_frame.PNG" id="elf" class="race elf_container"/>
</div>
var imageNodes = document.getElementsByClassName("race");
for(var i = 0; i < imageNodes.length; i++){
imageNodes[i].addEventListener('click', (e) =>{
const imageId = e.target.id;
document.getElementById('imageChange').src = 'dir/images/' + imageId + '.png';
})
}
On my website I have three images 1.png, 2.png and 3.png. When I click on 1.png, I want the animated gif 1a.gif to be loaded and shown/updated in the img tag located in <div id="container">. When I click on 2.png, 2a.gif should be displayed (while 1a.gif vanishes) and so on... This is my code:
<html>
<body>
<div>
<img src="1.png" onclick="document.getElementById('img').src = '1a.gif'" />
<img src="2.png" onclick="document.getElementById('img').src = '2a.gif'" />
<img src="3.png" onclick="document.getElementById('img').src = '3a.gif'" />
</div>
<div id="container">
<img id="img" src="1a.gif" />
</div>
</html>
</body>
It is working, however unreliable (tested with firefox and chrome)! When I refresh the html page and click on 1.png, than on 2.png ... suddendly at one point only the first frame of the animated gif is shown. I have to click on the same image (1,2 or 3.png) again in order to make the gif run. Why? I am looking for a light weight javascript solution without jquery. I am just asking myself why the gif is not played properly once I click on the image.
As a side note: It would be nice to show a loading image while the gif (5 MB) is loading. I failed to achive that using css:
#container {background:url('loading.png') no-repeat; }
In this case the loading image doesn't show up at all. Probably because I am updating directly from one (e.g. 1a.gif) to another (e.g. 2a.gif).
Showing it right before loading the gif did not help as well:
<img src="1.png" onclick="document.getElementById('img').src = 'loading.png';
document.getElementById('img').src = '1a.gif'" />
There are many ways of implementing this kind of thing, but to keep in line with how you're doing it, you'll want to hook into the onload event of the img.
Note that in this snippet, I don't have access to your GIFs, so I'm using the dummyimage.com service, which is pretty fast, so you don't see the "loading" for very long.
window.onload = function() {
var img = document.getElementById('img');
var container = document.getElementById('container');
var showImage = function showImage() {
img.style.display = "inline";
container.style.backgroundImage = "";
};
img.addEventListener('load', showImage);
img.addEventListener('error', showImage);
var thumbs = document.getElementsByClassName('thumb');
for (var i = 0, z = thumbs.length; i < z; i++) {
var thumb = thumbs[i];
var handler = (function(t) {
return function clickThumb() {
container.style.backgroundImage = "url('https://dummyimage.com/500x500/000/fff.gif&text=loading')";
img.style.display = "none";
img.src = t.dataset['image'];
};
})(thumb);
thumb.addEventListener('click', handler);
}
};
<div>
<img src="1.png" class="thumb" data-image="https://dummyimage.com/500x200/000/fff.gif" />
<img src="2.png" class="thumb" data-image="https://dummyimage.com/200x200/000/fff.gif" />
<img src="3.png" class="thumb" data-image="https://dummyimage.com/500x500/000/fff.gif" />
</div>
<div id="container">
<img id="img" class="main" />
</div>
This happens bacause the second img is not loaded yet!
I suggest you to put the 2 img in 2 different divs and the use javascript to hide/show the entire div!
I am new to JavaScript and I'm working on something. This is what I've reached so far and here is my code:
<!DOCTYPE html>
<html>
<head>
<title>Image Editor V 1.0</title>
<script>
function changeOpacity(newValue) {
document.getElementById("span").innerHTML = newValue*100 +'%';
document.getElementById("image1").style.opacity = newValue;
}
var color = true;
function imgColor() {
if (color) {
document.getElementById("image1").style.WebkitFilter = "grayscale(100%)";
color = false;
} else {
document.getElementById("image1").style.WebkitFilter = "none";
color = true;
}
}
function colorImg() {
document.getElementById("image1").style.WebkitFilter = "none";
}
function greyImg() {
document.getElementById("image1").style.WebkitFilter = "grayscale(100%)";
}
function userImage() {
var link = document.getElementById("userImg").value;
document.getElementById("image1").src = link;
}
</script>
</head>
<body>
<button onclick="colorImg()">Colored</button>
<button onclick="greyImg()">Greyscale</button>
<button onclick="imgColor()" >Alternate</button><br><br>
Opacity :<input type="range" min="0" max="1" value="1" step="0.2" onchange="changeOpacity(this.value)"/>
<span id="span">100%</span> <br><br>
Try your own image! <input id="userImg" type="text" placeholder="Enter url here">
<button onclick="userImage()">Go!</button>
<br><br>
<img class="myImages" id="image1" src="image4.jpg">
<img class="myImages" id="image2" src="image2.jpg">
<img class="myImages" id="image3" src="image3.jpg">
</body>
</html>
So far, the "Colored", "Greyscale", and "Alternate" buttons along with the opacity slider work as intended only on the first image (image1.jpg). Also, when the user inputs his own image, it replaces the first image and the functions work on it as intended. Here is what am trying to do:
1 - Let the user select which of the three images he wants to edit by clicking on it, then apply a border around it and use it in the other functions (greyscale and opacity). Here's what I tried (but didn't work):
<img class="myImages" id="image1" src="image4.jpg" onclick="selectImg(this.id)">
<img class="myImages" id="image2" src="image2.jpg" onclick="selectImg(this.id)">
<img class="myImages" id="image3" src="image3.jpg" onclick="selectImg(this.id)">
function selectImg(imgID) {
document.getElementById("imgID").style.border = 50px;
}
2 - When the user inputs his own image, I want it to replace all the 3 images I have displayed by default.
Your help is greatly appreciated. Thanks in advance!
You are missing quotes both on the id and the 50px. But it is better to define a style for the selection.
Then let a click handler first remove that style from all the images, except the clicked image, where it should set that style. The functions .classList.add and .classList.remove can be used for that.
Where you currently have document.getElementById('image1'), you would do instead:
document.querySelector('.selected')
Then you should also make sure that the page loads with one image selected, i.e. with the selected class.
Some other improvements make sure that when changing the selection, the opacity slider is also brought in line with that image's current opacity setting.
Here is a snippet that does all that:
function changeOpacity(newValue) {
document.getElementById("span").textContent = newValue*100 +'%';
document.querySelector(".selected").style.opacity = newValue;
document.querySelector('input[type=range]').value = newValue;
}
function getOpacity() {
return parseFloat(document.querySelector(".selected").style.opacity || '1');
}
function isColor() {
return document.querySelector(".selected").style.WebkitFilter !== "grayscale(100%)";
}
function imgColor() {
document.querySelector(".selected").style.filter =
document.querySelector(".selected").style.WebkitFilter =
isColor() ? "grayscale(100%)" : "none";
}
function colorImg() {
if (!isColor()) imgColor()
}
function greyImg() {
if (isColor()) imgColor()
}
function userImage() {
document.querySelector(".selected").src = document.getElementById("userImg").value;
}
// Add this function, and call it on click on an image
function select(img) {
Array.from(document.querySelectorAll('.myImages')).forEach(
myImg => myImg === img ? myImg.classList.add('selected')
: myImg.classList.remove('selected')
);
// bring opacity slider in line with selected image
changeOpacity(getOpacity());
}
.selected {
border: 1px solid;
}
<button onclick="colorImg()">Colored</button>
<button onclick="greyImg()">Greyscale</button>
<button onclick="imgColor()">Alternate</button><br><br>
Opacity :<input type="range" min="0" max="1" value="1" step="0.2" onchange="changeOpacity(this.value)"/>
<span id="span">100%</span> <br><br>
Try your own image! <input id="userImg" type="text" placeholder="Enter url here">
<button onclick="userImage()">Go!</button>
<br><br>
<img class="myImages selected" id="image1" onclick="select(this)"
src="//cdn.sstatic.net/Sites/stackoverflow/company/img/logos/se/se-icon.png?v=93426798a1d4">
<img class="myImages" id="image2" onclick="select(this)"
src="http://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png?v=c78bd457575a">
<img class="myImages" id="image3" onclick="select(this)"
src="http://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/sf/sf-icon.png?v=6c3100d858bb">
First - you are not using that imgID, but String like that variable. Change to:
function selectImg(imgID) {
document.getElementById(imgID).style.border = 50px; //notice no quotes for imgID
activeImage = imgID; //set activeImage ID
}
And then when you are doing something to an image, don't use "image1", but activeImage that is global variable (defined outside and before functions).
And as for new uploaded image:
Put it into another div and work with such algorithm -
when (uploaded_new)
hide default pics
show DIV with new image
activeImage = uploadedPic