JavaScript/HTML - Replace GIF instead of adding by button click - javascript

I have already seen a couple of the same questions but I can't seem to get it right. I want to generate a new GIF with a button click. I got as far as generating a GIF by a button click. The problem is that when I click the button again it adds another GIF instead of replaced the previous one.
This is the code I have now:
HTML Button
<form>
<button
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg"
type="button"
id="btnGIF"
style="display: inline;
transition: all 0.15s ease 0s;
text-align: center;
width: 50%;
z-index:1;
position: relative;
padding: 3%;">Generate GIF
</button>
</form>
And this is the JavaScript code I have:
document.addEventListener("DOMContentLoaded", init);
function init() {
document.getElementById("btnGIF").addEventListener("click", ev => {
let APIKEY = "Dsuxat5V1ccrtvIIBdrxk731WPrSs22l";
let RandomNumber = Math.floor(Math.random() * (100 - 1) + 1);
ev.preventDefault();
let url = `https://api.giphy.com/v1/gifs/search?api_key=${APIKEY}&limit=100&q=thankyou&offset=${RandomNumber}`;
console.log(APIKEY)
console.log(url);
//var image_x = document.getElementsByClassName('out').classList.length;
//console.log(image_x);
//if (image_x > 0){
// PrevImage = document.getElementsByClassName('out')
// PrevImage[0].parentNode.removeChild(PrevImage[0]);
// }
fetch(url)
.then(response => response.json())
.then(content => {
console.log(content.data);
console.log('META', content.meta);
let fig = document.createElement("figure");
let img = document.createElement("img");
img.src = content.data[0].images.downsized.url;
img.alt = content.data[0].title;
fig.appendChild(img);
let out = document.querySelector(".out");
out.insertAdjacentElement("afterbegin", fig);
})
.catch(err => {
console.error(err);
})
});
}
I do see that I'm appending the new gif instead of replacing it. I just can't find a way to replace it (I just started learning JavaScript).
Could someone help me?

You have to remove the previous gif from the html element that it is being appended, which in this case is the element with class 'out'. An easy way to do this is to clear all the children from that class before appending the new element. The snippet below will be setting the HTML of the children of the 'out' class to blank.
document.querySelector(".out").innerHTML = ""
You can put this line right above where you set the api key, the first line within the click listener. Also, it is good practice not to post your api key on stack overflow. Best to leave that blank here.

Related

assistance regarding fetching and displaying a display:none back to my page

this is my code:
const clcBtn = document.getElementById("calcButton");
let clcInput = document.getElementById("calcInput");
const result = document.getElementById('paragraph');
const loader = document.getElementById('spinner');
clcBtn.addEventListener("click", calcFunc);
function calcFunc() {
loader.classList.add("display")
fetch(`http://localhost:5050/fibonacci/`).then(function (response) {
return response.json().then(function (data) {
result.innerHTML = data.clcInput.value; // i want to get the input value from the input field and the server to calculate it and present it to the user.
});
});
}
basically what i want to do, is to add the value the user types in to the innerHTML paragraph id name.
and then i want to make the button react to the click and re-display the "loader" (which i gave it display:none in the CSS file)
and then, i need to make the button to display an error message if the input is higher than 50.
what i have tried to do:
inside the
clcBtn.addEventListener("click", calcFunc);
function calcFunc() {
i have tried to add:
loader.classlist.add("display")
and inside
return response.json().then(function (data) {
result.innerHTML = data.clcInput.value;
i have tried to add and change it to:
clcInput.value = innerHTML.result;
what am i doing wrong?
what is wrong with my syntax and what is the order i need to write everything?
thank you!!!
If i understand correctly what is you need, you should look at the small snippets I did below. It show a loader during the API Call and hide it when you get the result as well as updating the info paragraph depending on the value you typed.
The main thing I recommend you changing in order for your code to work properly is not adding or removing a class to your spinner element to hide it and show it, but simply changing directly it's style by using loader.style.display = "value"
Hope it helps.
const clcBtn = document.getElementById("calcButton");
let clcInput = document.getElementById("calcInput");
const result = document.getElementById('paragraph');
const loader = document.getElementById('spinner');
clcBtn.addEventListener("click", calcFunc);
function calcFunc() {
paragraph.innerText= "";
loader.style.display = "block";
// TimeOut to simulate API Call
setTimeout(function() {
loader.style.display = "none";
if (clcInput.value > 50) {
paragraph.innerText = clcInput.value + " - Error, value too high";
} else {
paragraph.innerText = clcInput.value + " - Value correct";
}
}, 2000);
}
#spinner {
width: 50px;
height: 50px;
border-radius: 50%;
background-color: white;
border: 5px solid black;
display: none;
}
<input type="number" id="calcInput" />
<button id="calcButton">calcButton</button>
<div id="spinner"></div>
<p id="paragraph"></p>

Querying html for an id in JS

I am in the process of completing CS50 and a took the WEB Tracks. I am currently searching for a solution with a JS problem.
function blink() {
let body = document.querySelector('body');
if (body.style.visibility === 'hidden') {
body.style.visibility = 'visible';
} else {
body.style.visibility = 'hidden';
}
}
// Blink every 500ms
window.setInterval(blink, 500);
This is a working solution, however I need to alter it so that it selects all specific ids. For example id="image". I found an adaptation that only select 1 picture and makes it blink. How do i make all three blink?
There is an obvious solution with writing more code, but i hope there is another way
you will try with:
document.querySelector('#image') // return first item
document.querySelectorAll('#image') // return array items
document.getElementById('image') // similar to querySelector('#image')
maybe you can try with selector [id='image'] if for some reason #id not working properly.
example:
setTimeout(() => {
document.querySelector('#image').style.visibility = 'visible'
}, 2000);
let interval;
interval = setInterval(() => {
const image = document.querySelector('#image');
if (image && image.style.visibility !== 'hidden') {
clearInterval(interval);
alert("is visible");
}
}, 500);
<img style="visibility: hidden;" src="https://www.gravatar.com/avatar/dab6fe88b302678ad222467965a0423e?s=48&d=identicon&r=PG" id="image" />
css selectors(examples):
#someId - search by id
a - find a tag
[attribute='value'] - find by attribute value
.className - find by class
:not(.className) - find where not

Change the image with JS every time the button is clicked

I am trying to implement the following:
Change the image every time i click the button "next".
Right now the code gives me the very last image from the array book just after I click the button next once. Is there a way it can be done?
HTML code:
<body>
<div class="main_page">
<button type="button" id="start">Start</button>
<button type="button" id="next">Next</button>
</div>
</body>
JS code:
document.addEventListener('DOMContentLoaded', () => {
let book = [
{
name: 'page1',
img: 'img/page1.png'
},
{
name: 'page2',
img: 'img/page2.png'
},
{
name: 'page3',
img: 'img/page3.png'
}
]
const main_page = document.querySelector('.main_page');// with this variable I have conttrol of
// div with class .main_page
let mainImg = document.createElement('img') // similar to HTML tag <img>. this var-ble creates <img> tag in HTML Document
mainImg.setAttribute('src', book[0].img) // making attribute to <img> tag through JavaScript
main_page.appendChild(mainImg);// appending <img> tag to the div with class main_page
let next = document.getElementById('next');
const turnPage = (count) =>{
//if(mainImg.getAttribute("src") == 'img/page2.png') alert("hey")//mainImg.src = {firstpage}
next.addEventListener('click', () => {
if(mainImg.getAttribute("src") == book[count].img){
//alert("hey")
mainImg.src = book[count+1].img
}})
}
for(let i = 0; i< book.length; i++){
turnPage(i);
}
})
You have a few problems with your code, as others have pointed out. As Teemu said, you are adding 3 click listeners to the button. You also need to put the turn page function into your listener, instead of calling it outside. These are the main changes you need:
1: You need to declare a variable outside of the listeners and any loops to keep count of the pages
let count = 0;
2: Add a listener that will call your turnpage function on each click. In that listener, you need to check that the next page isn't greater than the total number of pages before calling turnPage- otherwise you will get an error when the code tries to access the image from a non-existent page.
(You could instead start again at page 1, but as you have a Start button I assumed that you will intend to use that instead of having a continuous loop).
next.addEventListener('click', () => {
if ((count+1) < book.length)
turnPage(count);
count++;
})
3: Finally, your turnPage function just needs to set up the next image
const turnPage = (count) => {
mainImg.src = book[count + 1].img
}
Here is the full working snippet:
document.addEventListener('DOMContentLoaded', () => {
let book = [{
name: 'page1',
img: 'https://lorempixel.com/output/animals-q-c-200-200-9.jpg'
},
{
name: 'page2',
img: 'https://lorempixel.com/output/animals-q-c-200-200-10.jpg'
},
{
name: 'page3',
img: 'https://lorempixel.com/output/animals-q-c-200-200-4.jpg'
}
]
const main_page = document.querySelector('.main_page'); // with this variable I have conttrol of
// div with class .main_page
let mainImg = document.createElement('img') // similar to HTML tag <img>. this var-ble creates <img> tag in HTML Document
mainImg.setAttribute('src', book[0].img) // making attribute to <img> tag through JavaScript
main_page.appendChild(mainImg); // appending <img> tag to the div with class main_page
let next = document.getElementById('next');
// set up your listener to turn the page on each click
next.addEventListener('click', () => {
let count = 0; // declare your variable for page count
// check if the next page is greater than the total number of pages
if ((count+1) < book.length)
turnPage(count);
count++;
})
// your turnPage function
const turnPage = (count) => {
if (mainImg.getAttribute("src") == book[count].img) {
mainImg.src = book[count + 1].img
}
}
})
<body>
<div class="main_page">
<button type="button" id="start">Start</button>
<button type="button" id="next">Next</button>
</div>
</body>
FYI I'm not sure what this line is for, but I've left it in, in case you need it for something you haven't included here:
if (mainImg.getAttribute("src") == book[count].img) {
Also, you could just use the count variable in your pageTurn without passing it in in the click listener. You could check if you are the the end in there - it all depends on how this fits in with the rest of what you need to do.
What Teemu said in the comments is right. I can't comment as my reputation is low. So providing the code here. Just remove turnPage function definition and for loop. And replace it with the code below.
let count = 0, len = book.length;
next.addEventListener('click', () => {
if(mainImg.getAttribute("src") == book[count].img){
count = (count + 1) % len;
mainImg.src = book[count].img
}
});
You can use array to store your image and then display it in your codes
But you also have to make sure you use <img src=""> tag
Example
<img src="" id="myImage">
<br />
<button type="button" id="next">Next</button>
//JavaScript Codes
//Get HTML Elements
let images = [];
let img = document.querySelector("#myImage");
let button = document.querySelector("#next");
let defaultIndex = 0;
//Make a function to be executed once you click the button
function makeIt() {
//Make sure defaultIndex won't be above your array
if (defaultIndex < images.length) {
//Then go to the next image using incrementation
defaultIndex += 1;
//Assign your new value to the img tag
img.src = images[defaultIndex];
}
You can even make previous feature by using decrement.
I hope this will help you. If you find any mistake, feel free to correct!

How can I remove lag on my image carousel?

I am trying to remove a lag on an image carousel on a personal website I have been working on. I was able to make the carousel work fine, but the images are really laggy until I make my way all the way through the carousel of the photoalbum (you can see what I have here). I have the code set up so that the image file locations are in an array and the src of the background image changes to a new location based on adding new text from the array. Do you have a recommendation on how I can remove the lag? I have tried a few things with the fetch api but I have only used this to fetch and parse json data so I am a bit confused on how to make it work on local files, but I assume I need to somehow make this asynchronous. Any help or resources you can share is greatly appreciated!
The button cycles through like so:
let album = 2;
let currSlide = 0;
divContainer.style.backgroundImage = picArray[album][currSlide];
right.addEventListener('click', () => {
if(currSlide == picArray[album].length - 1){
currSlide = 0;
divContainer.style.backgroundImage = picArray[album][currSlide];
}
else {
currSlide = currSlide + 1;
divContainer.style.backgroundImage = picArray[album][currSlide];
}
});
and the array looks like this:
let picArray = [
[ "url('Pictures/Amsterdam/1.jpg')",
"url('Pictures/Amsterdam/2.jpg')",
"url('Pictures/Amsterdam/3.jpg')",
"url('Pictures/Amsterdam/4.jpg')",
"url('Pictures/Amsterdam/5.jpg')",
"url('Pictures/Amsterdam/6.jpg')",
"url('Pictures/Amsterdam/7.jpg')",
"url('Pictures/Amsterdam/8.jpg')",
"url('Pictures/Amsterdam/9.jpg')"
],
[ "url('Pictures/OregonCoast/1.jpg')",
"url('Pictures/OregonCoast/2.jpg')",
"url('Pictures/OregonCoast/3.jpg')",
"url('Pictures/OregonCoast/4.jpg')"
]
Your images are too long, so it take time to load.
One way to improve. Load image before ur carousel started. Use show hide to toggle.
Pre cache images using the network.
Use a small image for display in thumbnail.
See the sample below.
let album = 2;
let currSlide = 0;
const divContainer = document.getElementById("images");
const right = document.getElementById("rightB");
let picArray = [
"https://nickcosmo.com/Pictures/RoseGarden/1.jpg",
"https://nickcosmo.com/Pictures/RoseGarden/2.jpg",
"https://nickcosmo.com/Pictures/RoseGarden/3.jpg",
"https://nickcosmo.com/Pictures/RoseGarden/4.jpg",
];
divContainer.innerHTML = picArray.map((src) => `<img src="${src}" />`).join("");
const images = divContainer.querySelectorAll("img");
let index = 0;
images[index].classList.add("active");
right.addEventListener("click", () => {
images.forEach((img) => img.classList.remove("active"));
images[index++].classList.add("active");
});
#images img {
display: none;
}
#images .active {
display: block !important;
}
<div class="carousel">
<button class="moveB" id="leftB">‹</button>
<button class="moveB" id="rightB">›</button>
<div id="images">
</div>
</div>

Copy URL to clipboard and show and hide message

Would like to copy current URL to clipboard show a notice message and hide again after few seconds. I've seen this function online.
The animated gif shows how it should work. Javascript part is extracted from a website with a working example and the same HTML and CSS code used, but the javascript is not formatted correctly yet, because i extracted only the part this function needs. Can someone help me write the javascript correctly? Fiddle is ready to go:
Fiddle example
Extracted javascript
events: {
"click .share": "onShareClick"
},
onMouseEnter: function() {},
onShareClick: function(e) {
var t = this;
this.$el.find(".share").addClass("show-notice"), setTimeout(function() {
t.$el.find(".share").removeClass("show-notice")
}, 3e3);
var n = document.createElement("textarea");
n.value = location.href, document.body.appendChild(n), n.select(), document.execCommand("copy"), document.body.removeChild(n)
},
HTML
<div class="share">
<img src="images/share.svg">
<span class="share-notice">Link copied to clipboard</span>
<span class="mouseenter-notice">Share</span>
</div>
Assuming the div is the first of member of the 'share' class within the doc you could try:
const div = document.getElementsByClassName('share')[0];
const shareNotice = document.getElementById('share-notice');
const mouseoverNotice = document.getElementById('mouseover-notice');
div.onclick = () => {
window
.navigator
.clipboard
.writeText(window.location.href);
shareNotice.style.display = 'initial';
window.setTimeout(() => shareNotice.style.display = 'none', 1500);
};
div.onmouseover = () => mouseoverNotice.style.display = 'initial';
div.onmouseleave = () => mouseoverNotice.style.display = 'none';
.share { cursor: pointer }
#share-notice { display: none; }
#mouseover-notice { display: none; }
<div class="share">
x
<span id="share-notice">Link copied to clipboard</span>
<span id="mouseover-notice">Share</span>
</div>
Take a look at the clipboard API: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API
For convenience you might want to use clipboard js: https://clipboardjs.com/
You can access the current url with window.location.href.

Categories

Resources