Prevent Image Caching - Javascript - javascript

This function is supposed to grab a random image from the url everytime its called
function grabImg(){
var img = document.createElement('img');
img.src = 'https://picsum.photos/200/300';
document.getElementById('flex-cat').appendChild(img);
}
And display it in the div below
<div class="container-1">
<h2>Image Grabber</h2>
<button class="btn btn-success" onclick="grabImg()">Grab Image</button>
<div class="flex-box-container-2" id="flex-cat"></div>
</div>
Initially when the button is clicked, it calls the function and displays an image fine. However when the button is clicked on multiple times, instead of displaying different random images, the same image which was shown the first time keeps being displayed.
Any tips on how to prevent this?

Using picsum documentation, see Advanced Usage, you can request multiple images of the same size in your browser, add the random query param to prevent the images from being cached. Then you can randomize the number using a helper function, then concatenate using string literal => img.src = https://picsum.photos/200/300?random=${randomRange(10000)}.
EDIT:
To make it truly random, track the random numbers created with the helper function using an array. If the value is present in the array already, then run the randomImage method again, else push the value into the array for tracking purposes and return the random value.
const arr = []
function randomImage() { // get a random number
let num = ''
let tempRan = Math.random()
if(!arr.includes(tempRan)){
num = tempRan
arr.push(num)
}else{
randomImage()
}
return arr[arr.length-1]
}
function grabImg() {
var img = document.createElement('img');
img.src = `https://picsum.photos/200/300?random=${randomImage()}`;
document.getElementById('flex-cat').appendChild(img);
}
<div class="container-1">
<h2>Image Grabber</h2>
<button class="btn btn-success" onclick="grabImg()">Grab Image</button>
<div class="flex-box-container-2" id="flex-cat">
</div>
</div>

Related

Prevent createElement from creating multiple identical images

I am going to try and be as thorough as possible on this so stick with me.
My program takes user input entered on a form. This input goes through a range of if statements that will set variables to true, these variables that are set to true will then use createElement to create img inside predetermined divs. There will always be at least one img created, and up to 4 imgs at the most. This is all completed by a button click.
I learned createElement will continuously createElement with each button click posting the img right next to the original img and will do this infinitely or until the page is reloaded.
My solution was to create a counter that incremented each time the button was clicked. That took care of any extra createElements. Then I thought if the user first entered a large number that will create 2 separate and individual images say... image 1 and image 2 (which is desired), then if the user enters a lower number that only creates image 1, then image 2 would still be posted (unwanted). Of course a page refresh would clear the images created and avoid this.
So I'm not quite sure what to do...
Ideally when the button is pressed a second time then all old createElements would be cleared, and all new createElements would populate.
I removed the counter for the purpose of this question
poster__#'s are the called id's...
const movieTime = 30;
var userTimeAvailable = 25;
const button = document.getElementById("calculate");
button.onclick = function calculateTime() {
if (userTimeAvailable < movieTime) {
console.log(
"You have enough time to watch " +
Math.round((userTimeAvailable / movieTime) * 100) +
"% of the movie."
);
displayMoviePoster1 = true;
}
moviePosterGenerator();
}
function moviePosterGenerator() {
if (displayMoviePoster1 === true) {
var par = document.getElementById("poster__2");
var theatricalMoviePoster = document.createElement("img");
theatricalMoviePoster.src = "imgURL";
par.appendChild(theatricalMoviePoster);
}
}
<button class="button" id="calculate">calculate</button>
<div class="movie-poster__container" id="posters">
<div class="movie-poster" id="poster__1"></div>
<div class="movie-poster" id="poster__2"></div>
<div class="movie-poster" id="poster__3"></div>
<div class="movie-poster" id="poster__4"></div>
</div>

Can I save a random generated var so I can call the result back later in javascript

I'm working on a project where I generate a random var to create random scenes. One of them is location. I want it to be possible to generate a location with one button. Then press another button to generate a new location and when I press on the first button I want to get back the generated location I generated with that button
The function I generate the location with looks like this
function inhoudFunction()
{
var locs = ["movie", "park", "garden", "home"];
var loc = locs[Math.floor(Math.random()*locs.length)];
document.getElementById('inhoud').innerHTML="<h2>Locatie</h2>" + loc;
And these are the buttons I use to run the codes
<button type="button" onclick="introFunction()">intro</button>
<button type="button" onclick="midFunction()">mid</button>
To know if the button was pressed twice I used this code
function introFunction(){
if (introClicked == 1){
document.getElementById('introClicked').innerHTML="<div id=inhoud></div>";
}
else{
document.getElementById('introClicked').innerHTML="<div id=inhoud></div>";
inhoudFunction();
introClickedFunction();
}
And introClicked gets updated with this function
var introClicked = 0;
function introClickedFunction(){
introClicked = introClicked + 1;
}
But once I press the button twice I get nothing back
Save the generated value directly as a custom field of your <button> element.
In the example below, the element is passed to the click handler function as event.target. The function reads the gen_locations field. If it's not set, then it generates the random value and sets it.
window.addEventListener('DOMContentLoaded', _e => {
const locs = ["movie", "park", "garden", "home"];
document.getElementById('inhoud-button1').addEventListener('click', inhoudFunction);
document.getElementById('inhoud-button2').addEventListener('click', inhoudFunction);
function inhoudFunction(event) {
let genlocs = event.target.gen_locations;
if (!genlocs) {
genlocs = []
for (let i = 0; i < 2; i++) {
genlocs.push( locs[Math.floor(Math.random() * locs.length)] );
event.target.gen_locations = genlocs;
}
}
document.getElementById('inhoud').innerHTML = "<h2>Locatie</h2>" + JSON.stringify(genlocs);
}
});
<div id="inhoud"></div>
<button id="inhoud-button1">Inhound 1</button>
<button id="inhoud-button2">Inhound 2</button>
I've cleaned the code by avoiding inline javascript event handlers. Those are bad! :)
Edit: improved to show storing 2 generated randoms at once per button

Function executes only once when using onClick event [javascript]

I am trying to randomly change background image of a div (#reaction-background) after every click of a button (#angry) with onclick event.
However, the background image only changes once after clicking the button.
HTML:
<div class="btn-list">
<a id="angry">ANGRY</a>
<div id="reaction-background"></div>
Javascript:
// array of pictures
var fileNamesReactions = [
"angry1.jpg",
"angry2.jpg",
"angry3.jpg",
"angry4.jpg",
"angry5.jpg"
];
// random reaction index
var randomIndexReaction = Math.floor(Math.random() * fileNamesReactions.length);
// randomize pictures
document.getElementById("angry").onclick = function() {
document.getElementById("reaction-background").style.background = "url(./img/reactions/angry/" + fileNamesReactions[randomIndexReaction] + ")";
document.getElementById("reaction-background").style.backgroundRepeat = "no-repeat";
document.getElementById("reaction-background").style.backgroundSize = "contain";
}
Your click event handler is, in fact, running every time you click. The problem is that you are only generating a random number once, before any clicks happen and so you set the background image once and further clicks just set the same image over and over.
You need to move the random generator inside of the click callback so that a new random number is generated upon each click.
Also, don't use the onclick property of the element to set up the callback. While this approach works, it's outdated and you should use the more robust and standard .addEventListener() method to set up events.
In addition, do your styling in CSS as much as possible and use CSS classes.
Putting it all together:
// array of pictures
var fileNamesReactions = [
"angry1.jpg",
"angry2.jpg",
"angry3.jpg",
"angry4.jpg",
"angry5.jpg"
];
// Get your DOM references that you'll use repeatedly just once:
let backgroundElement = document.getElementById("reaction-background");
// randomize pictures
document.getElementById("angry").addEventListener("click", function() {
// You have to get a new random each time the click occurs.
var random = Math.floor(Math.random() * fileNamesReactions.length);
backgroundElement.style.background = "url(./img/reactions/angry/" + fileNamesReactions[random] + ")";
console.log(backgroundElement.style.background);
});
/* Use CSS classes as much as possible as they make code much simpler */
#reaction-background {
background-size:"contain";
background-repeat:"no-repeat";
}
<div class="btn-list">
<a id="angry">ANGRY</a>
<div id="reaction-background"></div>
</div>
Move the random number statement inside the onclick method so that it generate a new number on every click. Please find code below:
// array of pictures
var fileNamesReactions = [
"angry1.jpg",
"angry2.jpg",
"angry3.jpg",
"angry4.jpg",
"angry5.jpg"
];
// randomize pictures
document.getElementById("angry").onclick = function() {
// random reaction index
var randomIndexReaction = Math.floor(Math.random() * fileNamesReactions.length);
document.getElementById("reaction-background").style.background = "url(./img/reactions/angry/" + fileNamesReactions[randomIndexReaction] + ")";
document.getElementById("reaction-background").style.backgroundRepeat = "no-repeat";
document.getElementById("reaction-background").style.backgroundSize = "contain";
}

Generate html using Javascript

I have a gallery page that is updated often with new images. I use simple HTML to post the photos. My process currently is copy and paste the set of tags for a photo and change the number to correspond with the image file name. E.G. I change the number 047 to 048. Copy-Paste, change it to 049. This goes on until I have reached the number of additional photos. As you can see, this is very inefficient and there must be a better way of doing this. I was wondering if there is a simpler way to achieve this with Javascript? Perhaps generate additional tags by inputing a certain number or range?
Any ideas that would make this process efficient are welcomed please! Thank you!
<div class="cbp-item trim">
<a href="../assets/images/trim/img-trim-047.jpg" class="cbp-caption cbp-lightbox" data-title="">
<div class="cbp-caption-defaultWrap">
<img src="../assets/images/trim/img-trim-047.jpg" alt="">
</div>
</a>
</div>
You could use a templating solution. There are several libraries for that, but you can also implement it yourself.
Here is one way to do that:
Put the HTML for one image in a script tag that has a non-standard language property so the browser will just ignore it
Put some keywords in there that you'll want to replace, e.g. {url}. You can invent your own syntax.
Read that template into a variable
In the JS code, put all the images' URLs in an array of strings
For each element in that array, replace the keywords in the template string with that particular URL, and concatenate all these resulting HTML snippets.
Inject the resulting HTML into the appropriate place in the document.
Here is a snippet doing that:
// Add new images here:
var images = [
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/SNice.svg/330px-SNice.svg.png",
"https://nettemarie357.files.wordpress.com/2014/09/smiley-face.jpg?w=74&h=74",
];
// Load the template HTML
var template = document.querySelector('script[language="text/template"]').innerHTML;
// Use template to insert all the images:
container.innerHTML = images.map(url => template.replace(/{url}/g, url)).join('');
img { max-width: 50px }
<div id="container"></div>
<script language="text/template">
<div class="cbp-item trim">
<a href="{url}" class="cbp-caption cbp-lightbox" data-title="">
<div class="cbp-caption-defaultWrap">
<img src="{url}" alt="">
</div>
</a>
</div>
</script>
This would help you creating it programatically:
var new_row = document.createElement('div');
new_row.className = "cbp-item trim";
var a = document.createElement('a');
a.href = "../assets/images/trim/img-trim-047.jpg";
a.className= "cbp-caption cbp-lightbox";
document.body.appendChild(a);
var div = document.createElement('div');
div.className = "cbp-caption-defaultWrap";
var img = document.createElement('img');
img.src= "../assets/images/trim/img-trim-047.jpg";
div.appendChild(img);
a.appendChild(div);
new_row.appendChild(a);
If it is just about printing HTML, I suggest you to use plugins like Emmet for Sublime Text editor.
When you install this plugin and see how it works, you can simple create a complex html in a way that 'for' loop would do this. This will help you to change only the image/link number of every item.
Check the demo in the link, that I added.
Here's an example in Java Script that will generate the html you will need. Set the total to whatever number you need to generate the number of images you want.
var total = 47;
var hook = document.getElementById('hook');
// Main Node for SlideShow
var node = document.createElement('div');
node.classList = "cbp-item trim";
// Work out the correct number
var n = function(int) {
var length = int.toString().length;
return length === 1
? '00' + int
: length === 2
? '0' + int
: length
}
// Create the item
var createItem = function(int){
// Create Anchor
var a = document.createElement('a');
a.href = '../assets/images/trim/img-trim-' + ( n(int) ) + '.jpg" class="cbp-caption cbp-lightbox';
a.classList = 'cbp-caption cbp-lightbox';
// Create Div
var div = document.createElement('div');
div.classList = 'cbp-caption-defaultWrap';
// Create Image
var img = document.createElement('img');
img.src = '../assets/images/trim/img-trim-' + ( n(int) ) + '.jpg';
img.alt = 'gallery image';
// Finalise Dom Node
var container = div.appendChild(img)
a.appendChild(div);
// Return Final Item
return a
}
// Create Items
for (var i = 1; i < total + 1; i++) {
node.appendChild(createItem(i));
}
// Append Main Node to Hook
hook.appendChild(node);
<div id="hook"></div>

JavaScript AddEventListener not working

So I'm trying to make a slideshow where the user can click next to browse through pictures. I've created an array for the images:
var staff = new Array();
staff[0] = "/images/Isabelle.png";
staff[1] = "/images/Nook.png";
staff[2] = "/images/Timothy_Tommy.png";
staff[3] = "/images/Mabel.png";
staff[4] = "/images/Sable.png";
staff[5] = "/images/Labelle.png";
And a function for changing the images:
var i = 1;
function nextImage(){
document.getElementById("slide").src = staff[i];
if(i < staff.length)
i++;
else i = 0; //wraps around to first image
}
The addEventListener function call I added into a registerHandlers function that I initialize with onload:
document.getElementById("next").addEventListener("click",nextImage,false);
And the image and "next" button are placed in divs inside body:
<div class="container">
<img id ="slide" src="images/Isabelle.png" />
</div>
<div id="next">
<button type="button">Next</button>
</div>
I've tried looking up solutions and example code but I can't seem to make this work
Try adding the event handler as DHTML, so you don't have to wait for it to load the elements, just in case that's an issue:
<button type="button" onclick="nextImage();">Next</button>

Categories

Resources