JavaScript AddEventListener not working - javascript

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>

Related

Prevent Image Caching - 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>

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!

modular JavaScript to call modal window

I'm using a plugin in pure JavaScript.
Here's a syntax for creating one modal window.
var modalContent = new tingle.modal();
var btn = document.querySelector('.trigger-button-1');
var modalWindow = document.querySelector('.project1-modal');
btn.addEventListener('click', function () {
modalContent.open();
});
modalContent.setContent(modalWindow.innerHTML);
In all, I need to create 8 modal windows, it was achieved with the following code I've written myself:
myModalContent = new tingle.modal();
var myBtn = document.querySelectorAll('button.project__btn');
for (var i = 0; i < myBtn.length; i++){
myBtn[i].addEventListener("click", function(){
myModalContent.open();
// check if a btn has an attribute
if (this.hasAttribute('data-btn')) {
myModalContent.setContent(document.querySelector('.project' + this.getAttribute("data-btn") + '-modal').innerHTML);
// otherwise set it to display only the project 1 modal window
} else {
myModalContent.setContent(document.querySelector('.project1-modal').innerHTML);
}
});
}
HTML (for 8 list elements in all)
<li class="project">
...
<button type="button" class="project__btn" data-btn="1">More</button>
<div class="project4-modal">
...
</div>
</li>
The problem above is solved but since I'm not a very experienced in JavaScript, I'm looking forward to getting a feedback or even a suggestion on how to improve my code.

Getting the contents of a div using on-click functions

I am currently trying to implement a "button" of sorts using javascript. When a user clicks on the div, the div background should change colors, and there should be a pop up listing the device number. I am planning on using the number to redirect the client later. But right now, I can't get the clicking event to register. I had the event working correctly for a bit, but the value was always the final value of 'i'. My webpage also has JQuery in it.
Here's a JSFiddle and my relevant code.
http://jsfiddle.net/G3ADG/9/
HTML Structure:
<div class="device" id="device1" value="1">
<div class="device-name" id="deviceName1">Name1</div>
</div>
<div class="device" id="device2" value="2">
<div class="device-name" id="deviceName2">Name2</div>
</div>
<div class="device" id="device3" value="3">
<div class="device-name" id="deviceName3">Name3</div>
</div>
Javascript:
(function() {
var devices = document.getElementsByClassName("device");
for (var i = 0; i < devices.length; i++) {
devices[i].addEventListener("click", function () {
alert(i);
this.style.backgroundColor = "#000000";
})
}
})();
Any help or input is appreciated.
EDIT: Fixed the ClassName call. The alert returned is still wrong though.
If you are already using jQuery - What you are trying can be done with this -
$('.device').on('click',function(){
$(this).css('background-color','red');
})
Demo ---> http://jsfiddle.net/G3ADG/8/
Check this fiddle:
You just needed a closure to attach events
(function () {
var devices = document.getElementsByClassName("device");
for (var i = 0; i < devices.length; i++) {
(function (i) {
devices[i].addEventListener("click", function () {
alert(i);
this.style.backgroundColor = "#000000";
})
})(i);
}
})();
Instead of running a for loop, just run $('.device').each(). I also added an alert to get each div.device's value. See here: http://jsfiddle.net/G3ADG/10/
Edit: I did it with bind instead of an on click because that mirrored how he was doing it in plain JS. pXL's solution using on works just as well if you are not dynamically adding div.device.

Javascript fadein on mouseover works but doesn't fadeout

So real simply, I have figured out how to fade a div in on a mouseover call. But I want to know how to fade it out without simply duplicating the javascript opposite of what it already is and linking that to a onmouseout.
Here is my Javascript:
<script type="text/javascript">
function fadein(objectID){
object = document.getElementById(objectID);
object.style.opacity = '0';
animatefadein = function (){
if(object.style.opacity < 1){
var current = Number(object.style.opacity);
var newopac = current + 0.1;
object.style.opacity = String(newopac);
setTimeout('animatefadein()', 100);
}
}
animatefadein();
}
and my html
<div id="rolloverwrapper" style="opacity:0;"></div>
<div id="wrapper">
<div id="content">
<div id="button">
<img src="images/dj.png" onmouseover="fadein('rolloverwrapper');"/>
</div>
</div>
</div>
Try something like this:
<script type="text/javascript">
function fade(objectID, amount) {
var MIN_OPACITY = 0;
var MAX_OPACITY = 1;
object = document.getElementById(objectID);
animatefade = function() {
if(object.style.opacity < MAX_OPACITY && object.style.opacity > MIN_OPACITY){
var current = Number(object.style.opacity);
var newopac = current + amount;
object.style.opacity = String(newopac);
setTimeout('animatefade()', 100);
}
}
animatefade();
}
</script>
With the following HTML:
<img src="images/dj.png" onmouseover="fade('rolloverwrapper', 0.1);" onmouseout="fade('rolloverwrapper', -0.1);"/>
If the behavior you want is the opposite of what you already have, but on a different event, then simply do it. Don't look for fancy solutions when you know a simple one already and it works.
Add a parameter to your fadein function to specify the fade direction. 1/-1, 0/1, t/f, etc... and pass that in to your animatefadein.
Then you'd have
<img src="..." onmouseover="fadein('rolloverwrapper', 1)" onmouseout="fadein('rolloverwrapper, 0)" />
However, you should look into using jquery for this sort thing. The library would be a "heavy" compared to just these few lines of JS, but the flexibility you gain is vast.

Categories

Resources