Javascript image removal and append - javascript

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.

Related

How do I update the HTML when a button is clicked (change image when button is clicked)?

I'm trying to update the HTML when a button is clicked.
I have tried to solve this issue for a few hours now and I don't know if I'm stupid, but the images are not changing.
const slider = document.querySelector(".slider")
const btn = document.querySelector(".next")
const btn2 = document.querySelector(".previous")
const images = ['car.jpg', `left.jpg`]
window.addEventListener("load", iniliatizeSlider())
function iniliatizeSlider(){
var x = 0
cars = ''
cars += `<div class="slide">
<img src="${images[x]}" alt"client">
<br><br>
</div>`
slider.innerHTML = cars;
}
btn.addEventListener("click", consoleMsg)
btn2.addEventListener("click", consoleMsg2)
function consoleMsg(){
x=1
}
function consoleMsg2(){
x=0
}
<section id="slider-section">
<div class="container">
<div class="subcontainer">
<div class="slider-wrapper">
<h2>client showcase</h2>
<br />
<div class="slider"></div>
<div id="controls">
<button class="previous">
<img src="left.jpg" alt="previous client" />
</button>
<button class="next">
<img src="right.jpg" alt="next client" />
</button>
</div>
</div>
</div>
</div>
</section>
I was expecting the image to change when the button was clicked, but the image stayed the same, but the value of x changed.
Your initialize function is running once, when the page loads and at that point you are setting the image source to 0 and you never change it after that. You need to adjust the image source within the functions that react to button clicks. Now you do update x in those functions but nothing is ever done with x after that point.
A couple of other things... With .addEventListener(), you pass a reference to the callback function, not invoke the function, so the line should be: window.addEventListener("load", iniliatizeSlider) <-- no () after the function name.
Also, you don't need to replace the HTML on the page to update the image, you only need to update the image's src property.
See comments below:
// Get a reference to an existing image element.
// No need to recreate the <img> element.
const img = document.querySelector(".slider img");
const next = document.querySelector(".next");
const prev = document.querySelector(".previous");
const images = ["https://cache.mrporter.com/content/images/cms/ycm/resource/blob/1252204/68e7f03297f41cb3ce41f15ec478f70f/image-data.jpg/w1500_q80.jpg", "https://play-lh.googleusercontent.com/VC7rta8PIK3MqmQG5c-F5CNJQ6cCv6Eb-kyBoUcQ2xj83dZVhn7YCj_GIWW8y7TnAMjU=w240-h480-rw"];
let currentIndex = 0; // Keeps track of which image is shown
next.addEventListener("click", function(){
// Check to see if we're at the end of the array
if(currentIndex === images.length-1){
currentIndex = 0; // Reset index
} else {
currentIndex++; // increase the index
}
img.src = images[currentIndex]; // Just update the existing image's source
});
prev.addEventListener("click", function(){
// Check to see if we're at the beginning of the array
if(currentIndex === 0){
currentIndex = images.length-1; // Reset index
} else {
currentIndex--; // decrease the index
}
img.src = images[currentIndex]; // Just update the existing image's source
});
img { width:50px; }
<section id="slider-section">
<div class="container">
<div class="subcontainer">
<div class="slider-wrapper">
<h2>client showcase</h2>
<br >
<div class="slider">
<!-- Here, we just put a static image element with the first image we want to see. -->
<img src="https://cache.mrporter.com/content/images/cms/ycm/resource/blob/1252204/68e7f03297f41cb3ce41f15ec478f70f/image-data.jpg/w1500_q80.jpg">
</div>
<div id="controls">
<button class="previous">
<img src="left.jpg" alt="previous client">
</button>
<button class="next">
<img src="right.jpg" alt="next client">
</button>
</div>
</div>
</div>
</div>
</section>
Call the function initializeSlider() on click of btn instead of consoleMsg().

Is there a way to simplify the detection the index number of a button with the same div class and load it's corresponding image?

So I managed to get the images I set under the same class to load up their respective fullsized images when clicked on.
However, I remembered seeing there was a way to simplify it further?
This is what I have so far, that is working out fine, but just needs to be simplified for convenience:
**The HTML:**
<div class="section-waterSustains" id="water_Sustains">
<h3>How water sustains nature</h3>
<br>
<div class="waterSustains_collagesht">
<!----Creating the collage picture-->
<div class="waterSustains_collagepic">
<img class="ws-collagePic" id="collagePic1" src="images/africa-deer-drinking-water-preview.png">
<img class="ws-collagePic" id="collagePic2" src="images/Frog_During_Rain_preview.png">
<img class="ws-collagePic" id="collagePic3" src="images/Bird_drinking_Water_preview.png">
<img class="ws-collagePic" id="collagePic4" src="images/12_YT_SPARROW_preview.png">
<img class="ws-collagePic" id="collagePic5" src="images/Fishes-swiming-preview.png">
<img class="ws-collagePic" id="collagePic6" src="images/kitten_watching_rain_drops_roll_down_window_preview.png">
</div>
<p class="waterSustains_collageCaption">Click the Animals and Plants to see how they interact with Nature everyday!</p>
</div>
<!-----Creating Overlay and full image-->
<div id="overlayCollage01" class="collageOverlay">
<sl-icon-button name="x" label="Close button" circle size="large" id="overlay-CloseBtn"></sl-icon-button>
<img class="overlay-Content" id="img01" src="images/africa-deer-drinking-water.jpg">
</div>
<div id="overlayCollage02" class="collageOverlay">
<sl-icon-button name="x" label="Close button" circle size="large" id="overlay-CloseBtn"></sl-icon-button>
<img class="overlay-Content" id="img01" src="images/Frog_During_Rain_Wallpaper.jpg">
</div>
<div id="overlayCollage01" class="collageOverlay">
<sl-icon-button name="x" label="Close button" circle size="large" id="overlay-CloseBtn"></sl-icon-button>
<img class="overlay-Content" id="img01" src="images/Bird_drinking_Water.jpg">
</div>
<div id="overlayCollage01" class="collageOverlay">
<sl-icon-button name="x" label="Close button" circle size="large" id="overlay-CloseBtn"></sl-icon-button>
<img class="overlay-Content" id="img01" src="images/12_YT_SPARROW_1391748f.jpg">
</div>
<div id="overlayCollage01" class="collageOverlay">
<sl-icon-button name="x" label="Close button" circle size="large" id="overlay-CloseBtn"></sl-icon-button>
<img class="overlay-Content" id="img01" src="images/pexels-harrison-haines-3536511.jpg">
</div>
<div id="overlayCollage01" class="collageOverlay">
<sl-icon-button name="x" label="Close button" circle size="large" id="overlay-CloseBtn"></sl-icon-button>
<img class="overlay-Content" id="img01" src="images/kitten_watching_rain_drops_roll_down_window_9028683602.jpg">
</div>
</div>
----------------------End HTML-------------------------------------
**The Javascript:**
/*--------Creating Modal images for How Water sustains nature Collage-------*/
//Get Overlay
var overlay = document.querySelectorAll(".collageOverlay");
//Get image.
var collageImg = document.querySelectorAll(".ws-collagePic");
//Get overlay to be active on clicking on image
collageImg[0].onclick = function() {
overlay[0].style.display = "block";
}
collageImg[1].onclick = function() {
overlay[1].style.display = "block";
}
collageImg[2].onclick = function() {
overlay[2].style.display = "block";
}
collageImg[3].onclick = function() {
overlay[3].style.display = "block";
}
collageImg[4].onclick = function() {
overlay[4].style.display = "block";
}
collageImg[5].onclick = function() {
overlay[5].style.display = "block";
}
//Get icon button (x) that closes Overlay
var overlayClose = document.querySelectorAll("#overlay-CloseBtn");
// When the user clicks on icon button (x), close the overlay
overlayClose[0].onclick = function() {
overlay[0].style.display = "none";
}
overlayClose[1].onclick = function() {
overlay[1].style.display = "none";
}
overlayClose[2].onclick = function() {
overlay[2].style.display = "none";
}
overlayClose[3].onclick = function() {
overlay[3].style.display = "none";
}
overlayClose[4].onclick = function() {
overlay[4].style.display = "none";
}
overlayClose[5].onclick = function() {
overlay[5].style.display = "none";
}
--------------------------END Javascript--------------------------
Thanks mates!
Use the forEach() method when working with an array of a class. I have provided a simplified method for your code using forEach() methods.
var overlay = document.querySelectorAll(".collageOverlay");
var collageImg = document.querySelectorAll(".ws-collagePic");
var overlayClose = document.querySelectorAll("#overlay-CloseBtn");
Array.from(collageImg).forEach(function(collageImgArray, i) {
collageImgArray.addEventListener('click', function() {
overlay[i].style.display = "block";
});
});
Array.from(overlayClose).forEach(function(overlayCloseArray, i) {
overlayCloseArray.addEventListener('click', function() {
overlay[i].style.display = "none";
});
});
Here is a simple version:
let imgElement = document.querySelector("#overlay-image");
document.querySelector("#buttons-container").onclick = function(e) {
if(e.target.nodeName === "BUTTON") {
let imageName = e.target.getAttribute("data-image-name");
imgElement.src = "somepath" + imageName;
// only for demonstration since we have no real images
imgElement.alt = imageName;
}
}
<div id="buttons-container">
<button data-image-name="img15">show Image 15</button>
<button data-image-name="img27">show Image 27</button>
<button data-image-name="img3">show Image 3</button>
<button data-image-name="img5">show Image 5</button>
<button data-image-name="img11">show Image 11</button>
</div>
<img id="overlay-image" src="" alt="no image">

can some body help me with ng-mouseover and ng-mouseleave in angularjs?

I have a code like this in my html:
<div ng-mouseover="show_up()" ng-mouseleave="dont_show_up()" class="contain">
<img src="image/first_image.jpg">
<div class="overlay" ng-style="overlay">
show songs
</div>
</div>
<div ng-mouseover="show_up()" ng-mouseleave="dont_show_up()" class="contain">
<img src="image/second_image.jpg">
<div class="overlay" ng-style="overlay">
show songs
</div>
</div>
and this is my js code :
$scope.show_up = function () {
$scope.overlay={
"height":"100%"
};
};
$scope.dont_show_up = function () {
$scope.overlay={
"height":"0"
};
}
this is what I need to happen: whenever I hover on my first image it should add the style "height:100%"
to my first image, not both of them!
and when I hover on my second image it should add the style "height:100%"
to my second image, not both of them!
how can I fix this problem?
One solution would be passing some value to show_up() and dont_show_up() function, which identifies an image, say 1, 2 and then, inside function, change overlay variable to array and update appropriate item. ng-style="overlay" must be also changed to ng-style="overlays[0]"
--Edit
<div ng-mouseover="show_up(0)" ng-mouseleave="dont_show_up(0)" class="contain">
<img src="image/first_image.jpg">
<div class="overlay" ng-style="overlays[0]">
show songs
</div>
</div>
<div ng-mouseover="show_up(1)" ng-mouseleave="dont_show_up(1)" class="contain">
<img src="image/second_image.jpg">
<div class="overlay" ng-style="overlays[1]">
show songs
</div>
</div>
$scope.show_up = function (index) {
$scope.overlays[index] = {
"height":"100%"
};
};
$scope.dont_show_up = function (index) {
$scope.overlays[index] = {
"height":"0"
};
}
Well that becomes difficult to maintain when number of images increase
Second solution.
You can store all images as an array of objects and apply ng-repeat directive to loop through them.
<div ng-repeat="image in images" ng-mouseover="show_up(image.id)" ng-mouseleave="dont_show_up(image.id)" class="contain">
<img ng-src="image.src">
<div class="overlay" ng-style="image.overlay">
show songs
</div>
</div>
$scope.show_up = function (id) {
$scope.images.find(image => image.id === id).overlay = {
"height":"100%"
};
};
$scope.dont_show_up = function (id) {
$scope.images.find(image => image.id === id).overlay = {
"height":"0"
};
}
Not sure what you are trying to achieve since you state you want the image to change from 0 - 100% on the mouseover - but the ng-style is applied to the overlay. I assume you are trying to overlay the text over the image?
Anyway you don't need angular or even javascript for this - just CSS and apply a :hover on the parent level and style on the child element and you can achieve the desired outcome without the cost of the js.
.overlay {
height: 0;
overflow: hidden
}
.contain:hover .overlay {
height: 100%;
}
<div class="contain">
<img src="https://i.pinimg.com/originals/3e/6b/cd/3e6bcdc46881f5355163f9783c44a985.jpg" height="150">
<div class="overlay">
show songs
</div>
</div>
<div class="contain">
<img src="https://images-na.ssl-images-amazon.com/images/I/61W2FTW9ePL._AC_SL1500_.jpg" height="150">
<div class="overlay">
show songs
</div>
</div>

Show img ALT text inside a div

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>

How could I optimise this js event?

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';
})
}

Categories

Resources