Problem with slideshow in Javascript, images don't load - javascript

I've a problem with a slider I've to do for school.
The console return no error, but the images don't show in the slider. I'm on it for four days now and I can't figure out what is the problem, so it seems that I need your lights ! ^^
I used the console to check if "diaporama.js" is working and it is, the console.log at the end of "slider.js" is to check if my image path is ok and it is. I've absolutely no clue of what is going wrong.
Thank you in advance !
Here is my code :
HTML
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta property="og:url" content="" />
<title>Slider</title>
<link rel="stylesheet" href="slide.css">
</head>
<body>
<h1>Test</h1>
<div id="caroussel">
<img src="" alt="diapo1" id="diapo">
<div id="precedent" ><</div>
<div id="suivant" >></div>
</div>
<script src="diaporama.js"></script>
<script src="slide.js"></script>
</body>
</html>
diaporama.js
class Diaporama {
constructor(src, images) {
this.src = src;
this.images = images;
this.position = 0;
this.start();
}
slideLeft() {
if (this.position <= 0) {
this.position = this.images.length - 1;
} else {
this.position--;
}
this.src = this.images[this.position];
}
slideRight() {
if (this.position > this.length-1) {
this.position = 0;
}
else {
this.position++;
}
this.src = this.images[this.position];
}
start() {
this.src = this.images[this.position];
}
}
slide.js
var images = Array('img/caroussel1.png', 'img/caroussel2.jpg', 'img/caroussel3.jpg', 'img/caroussel4.jpg', 'img/caroussel5.jpg');
var src = document.getElementById("diapo").src;
var diaporama = new Diaporama(src, images);
setInterval(function () { diaporama.slideLeft(); }, 5000);
console.log(src);

At a minimum, it looks like one problem is that:
You have an image element with ID diapo in your HTML, and then in the DOM, which has an empty src attribute.
In slide.js, you attempt to create a new instance of the class Diaporama, called diaporama, using the empty src attribute that you have stored in the variable src in slide.js.
Since an img element needs a src attribute with an actual URL, in order to show the image at that URL, you are seeing nothing, since you have not provided a URL (You won't get an error either, since an empty src attribute is perfectly valid HTML, and causes no JS errors)
UPDATE IN RESPONSE TO COMMENTS
The critical issue (or oversight), is that you have:
a carousel element in the index.html file, which is then represented in the DOM (which is what we expect)
an instance of class Diaporama called diaporama in slide.js, which has no link to the DOM carousel that you want it to have: all diaporama has is a String, taken from the src attribute of the DOM carousel, which refers to the URL path of various images. The diaporama instance can never "reach out" and update the DOM carousel, given the code you have written.
Thankfully, the fix is very simple.
As you know, there needs to be link between the DOM and object that you have created; creating such a link is straight-forward and just involves DOM queries.
I have added a solution (I have placed ALL the JS in one file, rather than two files -- as you have -- but this is not important)
class Diaporama {
constructor(imgElem, images) {
this.imgElem = imgElem;
this.images = images;
this.position = 0;
this.start();
}
slideLeft() {
if (this.position <= 0) {
this.position = this.images.length - 1;
} else {
this.position--;
}
// this is part of the 'bridge' between "carousel.js" and the DOM
this.imgElem.src = this.images[this.position];
}
slideRight() {
// there was an error in your original "slideRight" method: a typo and an "off-by-error"
if (this.position >= this.images.length-1) {
this.position = 0;
}
else {
this.position++;
}
// this is part of the 'bridge' between "carousel.js" and the DOM
this.imgElem.src = this.images[this.position];
}
start() {
// this is part of the 'bridge' between "carousel.js" and the DOM
this.imgElem.src = this.images[this.position];
}
}
// prefer an Array literal rather than call to Array -- less verbose, and slightly faster
var images = ['img/one.jpg', 'img/two.jpg', 'img/three.jpg'];
// This is where 'bridge' between "carousel.js" and the DOM is created: we 'cache' a reference to the carousel 'img' element,
// which we will then modify from within the 'carousel' instance of class Diaporama
var imgElem = window.document.getElementById('carousel').querySelector('img');
var carousel = new Diaporama(imgElem, images);
carousel.start();
// create 'delegated' event listener on document, and trigger correct method of 'carousel' in response to user interaction
window.document.addEventListener('click', ev => {
const target = ev.target;
if(target.id === 'back_button') {
carousel.slideLeft();
} else if(target.id === 'next_button') {
carousel.slideRight();
}
});
.carousel {
max-height: 400px;
max-width: 600px;
background: rgb(250,250,200);
overflow: hidden;
}
.button-wrapper {
display: flex;
justify-content: space-around;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Carousel</title>
</head>
<body>
<h1>Carousel slider (OOP)</h1>
<section id="carousel" class="carousel">
<div class="button-wrapper">
<button id="back_button">Back</button>
<button id="next_button">Next</button>
</div>
<img src="" alt="carousel image">
</section>
<script src="carousel.js"></script>
</body>
</html>
I hope this helps answer your question!
If it does, then please mark my answer as the accepted one.
If you still have questions, then let me know, and I will do my best to answer them.

Related

JS: calling functions via buttons does not work anymore, if page is updated without reloading the page

I want to write a program with one html page, which i can update and fill with different elements via javascript with one button that stays the same in every version, which displays a modalBox. I made a very basic version of this: One page, that is filled with two buttons (next and last) for navigating through the pages and one to display the modal. In addition, i added a number, which is incremented oder decremented accordingly, when you click through the updated versions of the page.
var counter = 1;
function setUp(){
var c = document.getElementById("container");
var d = document.createElement("div");
d.setAttribute("id", "main");
d.innerHTML = counter;
var nxt = document.createElement("button");
var bck = document.createElement("button");
var modalBtn = document.createElement("button");
nxt.innerText = ">";
bck.innerText = "<";
modalBtn.innerText="Show Modal";
nxt.setAttribute("onclick","nextPage()");
bck.setAttribute("onclick","lastPage()");
modalBtn.setAttribute("onclick","showModal()");
d.appendChild(bck);
c.appendChild(d);
d.appendChild(nxt);
d.appendChild(modalBtn);
}
function showModal(){
var m = document.getElementById("modal");
m.style.display = "block";
}
function closeModal(){
var m = document.getElementById("modal");
m.style.display = "none";
}
function nextPage(){
var c = document.getElementById("container");
c.innerHTML="";
counter++;
setUp();
}
function lastPage(){
var c = document.getElementById("container");
c.innerHTML="";
counter--;
setUp();
}
setUp();
*{
padding: 0;
margin: 0;
}
#modal{
position: absolute;
width: 500px;
height: 300px;
background-color: black;
display: none;
}
#main{
background-color: aliceblue;
height: 500px;
width: 800px;
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="tryout.css">
<script src="tryout.js" defer></script>
<title>Document</title>
</head>
<body>
<div id="container">
<div id="modal"><button id="closeButton" onclick="closeModal()">Close</button></div>
</div>
</body>
</html>
The problem is: on onload, the modal button works fine (on click, the modal is displayed). As soon as i update (not reloading!) the page via the next- or back button, the modal button stops working (Error-message says the type of modalbutton is null). I have no clue why, because to my knowledge, the buttons are reinitiated by clicking on the next or back button (because the setUp()-function is called in the functions triggered by the buttons). As soon as I reload the page via the reload-button, it is working until i use one of the next and back buttons.
I am new to js, it's probable that I'm missing sth. obvious here :) Many Thanks!
On the "nextPage" and "lastPage" function , you're just removing the whole content (including the modal) from the div which associated container class.
That's why when you calling the "showModal" function , there is no element with modal id on the DOM. That's why its saying null.
you can follow what Sakil said on the comment or, in your both(nextPage & lastPage) functions,you can just remove the div with id main and add it later on "setUp" function.
I'm adding some code snippet below, hope it will help;
function nextPage() {
//grab the div with "main" id
let main = document.getElementById("main");
//remove it from document
main.remove();
counter++;
//add it again; what you're doing actually.
setUp();
}
function lastPage() {
//grab the div with "main" id
let main = document.getElementById("main");
//remove it from document
main.remove();
counter--;
//add it again; what you're doing actually.
setUp();
}
of course you should refactor the code base, cause there is lot more copy-pasting staff present, but I'm leaving that up to you.

Script that keeps checking if a collection of items is fully loaded

I have a page with a long list about 880 items (and growing), which are loading in batches. When the window loads the first batch has about 52 items. So I would like to write a function that until the list isn't complete, shows a simple "loading more..." disclaimer on the page and keeps checking with the "allItems" variable until these are fully loaded.
So far I came up with this function, but it just take the first loaded batch of 52 (allItems.length) into account and then of course meets its condition and stops.... (see screenshots) What am I doing wrong?
$(window).on("load", function() {
// get all Items
var calItems = $(".collection-item.w-dyn-item");
// count them
var calCount = calItems.length;
// loaded elements flag
var loadedCount = 0;
function countItems() {
var interval = setInterval(function() {
loadedCount++;
if (loadedCount > calCount) {
$(".load-more-wrapper").hide();
clearInterval(interval);
} else {
loadedCount++;
}
}, 1000);
}
countItems();
});
Just by what code is posted in OP I'm assuming that the page takes too long to load. There's a way to dynamically load a ton of HTML without any human perceptible delay.
get a copy of all of your divs as a string, if it changes have updates stored in localStorage (that is an entirely different problem which warrants it's own question). In the example, I have 999 divs generated as one string:
const htmlString = [...new Array(999)].map((_, idx) => {
`<div class='dyn'>${idx}</div>`).join('')
});
Next, create a document fragment. A document fragment is a "ghost" element, it's not part of the DOM, yet it can contain elements. When it is added to the DOM it disappears and leaves it's children within the DOM. This takes no time at all since it's only a single DOM operation instead of 999 nodes loading.
let frag = new DocumentFragment();
Then create a block element (in this example, it'll be a section). Then render that string (ie htmlString) in the section and add the section to the fragment.
const sec = document.createElement('section');
sec.innerHTML = htmlString;
frag.append(sec);
Finally, collect all of the divs into an array and then add the fragment to the DOM.
const nodeList = [...sec.querySelectorAll('.dyn')];
document.querySelector('main').append(frag);
Go ahead and test if you have a collection
console.log(nodeList[888].textContent);
.as-console-row::after { width: 0; font-size: 0; }
.as-console-row-code { width: 100%; word-break: break-word; }
.as-console-wrapper { max-height: 1.5em !important; max-width: 50%; margin-left: 50%; }
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style></style>
</head>
<body>
<main></main>
<script>
const htmlString = [...new Array(999)].map((_, idx) => `<div class='dyn'>${idx}</div>`).join('');
let frag = new DocumentFragment();
const sec = document.createElement('section');
sec.innerHTML = htmlString;
frag.append(sec);
const nodeList = [...sec.querySelectorAll('.dyn')];
document.querySelector('main').append(frag);
console.log(nodeList[888].textContent);
</script>
</body>
</html>

I have multiple lines of text that print in typewriter animation. However, when I refresh my browser the different lines of texts get mixed up

I have multiple lines of text that print in typewriter animation, but when I refresh my browser the different lines of texts get mixed up.
Something like this "****eI icsr eAahtmeedr .t hWiesl cWoembes ittoe muys iWnegb sHiTtMeL,. CSS, and JS.**"
Click around Run snippet 5 or 6 times and including the code buttons, and you will see it see the problem.
The intro is a automatic animation when you first land the page which reads "Hello! My name is Frank. Welcome to my Website."
Tell Me More button prints out "I created this Website using HTML, CSS, and JS."
Nice! button prints out "This website is to showcase my skills."
Ok prints out "You should hire me. Scroll down to see why."
This is just a template. I am actually very new to Java and getting familiar with CSS and HTML. I am creating a portfolio and also learning to code, so bear with me.
I am basically trying to copy this website here https://www.amysboyd.com
I would like the buttons to disappear like in the website, but I don't know how to do that.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Portfolio</title>
<link rel="stylesheet" href="Portfolio Styles.css" </head>
<body>
<div class="abouttextsection">
<h1 id='output'></h1>
<script>
var a = 0;
var introtxt = 'Hello! My name is Frank. Welcome to my Website.';
var speed = 50;
function aboutintro() {
if (a < introtxt.length) {
document.getElementById("output").innerHTML += introtxt.charAt(a);
a++;
setTimeout(aboutintro, 50);
}
}
window.onload = aboutintro;
var doc, bod, I, TypeMaker; // for use on other loads
addEventListener('load', function() {
doc = document;
bod = doc.body;
I = function(id) {
return doc.getElementById(id);
}
TypeMaker = function(element, interval) {
this.element = element;
this.interval = interval || 50;
var t = this,
r;
this.type = function(string) {
if (r) clearInterval(r);
var s = string.split(''),
l = s.length,
i = 0;
var p = 'value' in this.element ? 'value' : 'innerHTML';
this.element[p] = '';
r = setInterval(function() {
t.element[p] += s[i++];
if (i === l) {
clearInterval(r);
r = undefined;
}
}, t.interval);
}
}
var typer = new TypeMaker(I('output')),
First_test = I('First_test'),
Second_test = I('Second_test'),
Third_test = I('Third_test');
var testArray = [''];
var testArrayL = testArray.length;
First_test.onclick = function() {
typer.type('I created this Website using HTML, CSS, and JS.');
}
Second_test.onclick = function() {
typer.type('This website is to showcase my skills.');
}
Third_test.onclick = function() {
typer.type('You should hire me. Scroll down to see why.');
}
});
</script>
<div class="aboutsectionbutton">
<button id='First_test' type='button' value='Tell Me More' />Tell Me More</button>
<button id='Second_test' type='button' value='Nice!' />Nice!</button>
<button id='Third_test'>Ok</button>
</div>
</div>
</body>
</html>
Add fadeOut transition to css class ->
CSS:
.hidden {
visibility: hidden;
opacity: 0;
transition: visibility 0s .25s, opacity .25s linear;
}
And on click event just add this class ->
JS:
Second_test.onclick = function() {
this.classList.add('hidden')
typer.type('This website is to showcase my skills.');
}
jsfiddle

How can i put it background image on setAttribute method?

I'm making a simple program that cuts the circle evenly.
enter image description here
and I want to put it image using 'setAttribute' method.
but, It doesn't work as i thought.
here is my code.
<!DOCTYPE html>
<html lang="kr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{margin:0; padding:0;}
</style>
<script>
function elt(name, attributes){
var node = document.createElement(name);
if( attributes ){
for(var attr in attributes){
if(attributes.hasOwnProperty(attr)){
node.setAttribute(attr,attributes[attr]);
}
}
}
for(var i=2; i<arguments.length; i++){
var child = arguments[i];
if( typeof child == "string" ){
child = document.createTextNode(child);
}
node.appendChild(child);
}
return node;
}
window.onload=()=>{
const IMG_W_COUNT = 50;
const IMG_H_COUNT = 33;
const IMG_SUM = 1650;
for(var i=1,j=0;i<=IMG_SUM;i++,j+=18){
var ImageSaver = elt("div",{
class:"menu item"+i,
width:18+"px",
height:18+"px",
background:"url('paint.jpg')",
backgroundPosition:0+"px"+" "+j+"px"
});
document.body.appendChild(ImageSaver);
}
}
</script>
</head>
<body>
</body>
</html>
The elt function is a function that helps to easily generate an element.
I'd really appreciate your help.
background, height and width aren't attributes (except on a few elements, and there they are mostly deprecated), nor is backgroundPosition.
To set a CSS property value with a function use setProperty on a style declaration.
Make sure you use the CSS property name, which is background-position not backgroundPosition.
element.style.setProperty("name", "value");
You have to set CSS properties.
element.style.width=18+"px";
element.style.height=18+"px";
element.style.background="url('paint.jpg')";
element.style.backgroundPosition="top right";

Change a div background image using javascript if/else

I am trying to get the background image of a div to change at an interval. I created an Array with the images, and every few seconds the function should check the value of "x" against the array length. If X is less, x will increase by one and the background image will change to the next image in the array, otherwise it will set x=0 and restart the process.
The div and initial image shows up how I want, but nothing happens.
I know there are probably better ways to do this, but I am very new to Javascript and want to learn why this code doesn't work. Thanks in advance for the help!!
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>ImageChanger</title>
<style type="text/css">
#imagediv {
float:left;
border-style:ridge;
border-width:8px;
border-color:Green;
border-radius:15px;
width:1250px;
height:450px;
background-image:url(images/landscape1.jpg)
}
</style>
<script type="text/javascript">
function displayNextImage() {
var x;
If (x<imageArray.length) {
x=x+1;
document.getElementById("imagediv").style.backgroundImage=images[x];
}
else {
x=0;
document.getElementById("imagediv").style.backgroundImage=images[x];
}
function startTimer() {
setInterval(displayNextImage, 3000);
}
var imageArray=new Array();
images[0] = "images/landscape1.jpg";
images[1] = "images/landscape2.jpg";
images[2] = "images/landscape3.jpg";
images[3] = "images/landscape4.jpg";
</script>
</head>
<body>
<div id="imagediv">
</div>
</body>
</html>
If (x<imageArray.length) {..
should be
if (x<imageArray.length) {
Javascript is case-sensitive.
Also you have some missing braces like you are not closing
function displayNextImage() { ....
Use your browser console to debug. These syntax errors will be shown there.
As far as syntax issues go:
As #Zee stated, If should be lowercase (if)
Also, as #Zee and some others stated, you are not closing function displayNextImage() { with a closing brace }.
You are improperly defining the background-image property in your function, whereas you defined it correctly in the block of CSS. You must wrap the image name with url().
You are never calling your timeout function, startTimer.
You create a new array imageArray but then use an undeclared array images

Categories