Potential function overloading in javascript: naming issue - javascript

I am new to Javascript but I was able to piece together something to create a random background image on page load. This was successfully used for a Div object on the page.
Since this worked well, I wanted to use this command again for a second Div object on the same page. Both Divs had separate CSS style names so I thought this would be fine. However as soon as I use both commands together, only one will work.
I assumed it was an overloading problem, but I tried renaming everything I could and it still hasn't solved it. Is there something else I need to rename that I'm missing or do I need to frame the two separate commands differently?
Below is the JS code, CSS and HTML:
Thanks in advance!
/*! random background image 2*/
window.onload = function frontimage() {
var thediv2 = document.getElementById("topimg");
var imgarray2 = new Array("f1.svg", "f2.svg");
var spot2 = Math.floor(Math.random()* imgarray2.length);
thediv2.style.background = "url(img/f-img/"+imgarray2[spot2]+")";
thediv2.style.backgroundSize = "70%";
thediv2.style.backgroundAttachment = "fixed";
thediv2.style.backgroundRepeat = "no-repeat";
thediv2.style.zIndex = "2";
thediv2.style.backgroundColor = "rgba(255,204,255,0.5)";
}
/*! random background image 1*/
window.onload = function backimage() {
var thediv = document.getElementById("imgmain");
var imgarray = new Array("b1.jpg", "b2.jpg", "b3.jpg", "b4.jpg", "b5.jpg");
var spot = Math.floor(Math.random()* imgarray.length);
thediv.style.background = "url(img/b-img/"+imgarray[spot]+")";
thediv.style.backgroundSize = "100%";
thediv.style.backgroundAttachment = "fixed";
thediv.style.backgroundRepeat = "no-repeat";
thediv.style.zIndex = "1";
}
#bigimg {
clear: both;
float: left;
margin-left: 0;
width: 100%;
display: block;
}
#imgmain {
background: 50% 0 no-repeat fixed;
z-index: 1;
width: 100%;
}
#topimg {
z-index: 2;
position: absolute;
background-image: url(../img/f-img/f2.svg);
background-repeat: no-repeat;
background-position: 50% -25%;
background-size:contain;
width: 100%;
margin: auto;
padding: 0;
}
<div id="bigimg">
<section id="imgmain"></section>
<section id="topimg"></section>
</div>

With addEventListener, you can add as many event handlers as you want.
window.addEventListener('load', function frontimage() {
// ...
});
window.addEventListener('load', function backimage() {
// ...
});

You are overriding your first window.onload by reassigning the callback function.
Try this:
window.onload = function() {
frontimage();
backimage();
}

Related

Change of pictures over and over by using setInterval

Below is a program that is to loop pictures with fade-in effect.
It includes this statement:
opacity = Number(window.getComputedStyle(abc).getPropertyValue("opacity"));
I understand that this statement assigns the opacity value of a window object to a variable opacity, but there is no such opacity variable declaration of any elements in the program!
When I remove this statement, it only shows the first picture... And when I keep that statement, the program loops well with a fade-in effect.
Can anyone explain to me why such phenomenon happens?
Compare these two snippets:
With assignment to opacity (fading is working as expected):
var opacity = 0;
var arrindex = 0;
var arr1 = [
"https://via.placeholder.com/400x400?text=p1",
"https://via.placeholder.com/400x400?text=p2",
"https://via.placeholder.com/400x400?text=p3",
"https://via.placeholder.com/400x400?text=p4",
"https://via.placeholder.com/400x400?text=p5"
];
setInterval(changepcs, 3000);
function changepcs() {
if (arrindex == arr1.length) {
arrindex = 0
};
let abc = document.getElementById("picture");
let address = arr1[arrindex];
abc.style.backgroundImage = `url(${address})`;
abc.classList.remove("fadein");
opacity = window.getComputedStyle(abc).getPropertyValue("opacity");
abc.classList.add("fadein");
arrindex++;
}
body {
height: 100vh;
}
#picture {
background-repeat: no-repeat;
background-position: center;
background-size: 400px 400px;
width: 80%;
margin: auto;
height: 80%;
opacity: 0;
}
#picture.fadein {
opacity: 1;
transition: opacity 2s linear;
}
<div id="picture"></div>
Without assignment to opacity (no fading effect for second image):
var opacity = 0;
var arrindex = 0;
var arr1 = [
"https://via.placeholder.com/400x400?text=p1",
"https://via.placeholder.com/400x400?text=p2",
"https://via.placeholder.com/400x400?text=p3",
"https://via.placeholder.com/400x400?text=p4",
"https://via.placeholder.com/400x400?text=p5"
];
setInterval(changepcs, 3000);
function changepcs() {
if (arrindex == arr1.length) {
arrindex = 0
};
let abc = document.getElementById("picture");
let address = arr1[arrindex];
abc.style.backgroundImage = `url(${address})`;
abc.classList.remove("fadein");
// opacity = window.getComputedStyle(abc).getPropertyValue("opacity");
abc.classList.add("fadein");
arrindex++;
}
body {
height: 100vh;
}
#picture {
background-repeat: no-repeat;
background-position: center;
background-size: 400px 400px;
width: 80%;
margin: auto;
height: 80%;
opacity: 0;
}
#picture.fadein {
opacity: 1;
transition: opacity 2s linear;
}
<div id="picture"></div>
The difference is not related to the variable opacity: you are right; it's value is never used after that assignment and is therefore unnecessary.
However, the call of getComputedStyle(abc).getPropertyValue("opacity") still makes the difference -- you can omit the call of Number and the assignment of this expression without any negative consequence, but the expression must stay.
This getComputedStyle(abc).getPropertyValue("opacity") is a complex API: it needs to render the document to know exactly what the opacity value is, since in general such CSS values can be influenced by a lot of CSS rules. My hunch is that the engine performs a paint cycle in order to compute the real, rendered value of this property. That means the execution of this call takes some time -- at least until after the next paint cycle. The side effect of this paint job is that the removal of the fadein class has now also been rendered. And that means that when that fadein class is added again, it really triggers the animation.
Without this getComputedStyle(abc).getPropertyValue("opacity") evaluation, the engine does not wait for a paint cycle. That means it has not yet effectuated the class removal when it adds the fadein class again. By consequence, nothing really changes -- the fadein class was still applied on the rendering when it is already "added" again. That means there is no animation.
I was a bit puzzled by this effect of that expression too. I would have explicitly waited for a paint cycle to happen with the call to requestAnimationFrame so to execute code right before the next paint cycle, and then schedule a callback again to get code to execute after the next paint job (before the next one). That would be the moment I would be sure the CSS class fadein had been removed in the rendered document and it would be the right time to add it again -- so triggering the animation.
Like so:
var arrindex = 0;
var arr1 = [
"https://via.placeholder.com/400x400?text=p1",
"https://via.placeholder.com/400x400?text=p2",
"https://via.placeholder.com/400x400?text=p3",
"https://via.placeholder.com/400x400?text=p4",
"https://via.placeholder.com/400x400?text=p5"
];
setInterval(changepcs, 3000);
function changepcs() {
if (arrindex == arr1.length) {
arrindex = 0
};
let abc = document.getElementById("picture");
let address = arr1[arrindex];
abc.style.backgroundImage = `url(${address})`;
abc.classList.remove("fadein");
// Need to wait for a paint cycle to occur before
// adding the CSS class again
requestAnimationFrame(() =>
requestAnimationFrame(() => abc.classList.add("fadein"))
);
arrindex++;
}
body {
height: 100vh;
}
#picture {
background-repeat: no-repeat;
background-position: center;
background-size: 400px 400px;
width: 80%;
margin: auto;
height: 80%;
opacity: 0;
}
#picture.fadein {
opacity: 1;
transition: opacity 2s linear;
}
<div id="picture"></div>
Thanks for all your support to this question, it is highly believe as one of the answer here (from trincot) mention the statement: "getComputedStyle(abc).getPropertyValue("opacity")" provide some time interval that allows the paint of the removal of "fade-in" class here to be rendered. To prove this, I try to replace the statement by using setTimeout statement: "setTimeout(()=>abc.classList.add("fadein"), 3000);" and the job is done.
setInterval(changepcs,3000);
var opacity = 0;
var arrindex = 0;
var arr1 = [
"https://via.placeholder.com/400x400?text=p1",
"https://via.placeholder.com/400x400?text=p2",
"https://via.placeholder.com/400x400?text=p3",
"https://via.placeholder.com/400x400?text=p4",
"https://via.placeholder.com/400x400?text=p5"
];
function changepcs() {
if(arrindex == arr1.length){arrindex = 0};
let abc = document.getElementById("picture");
let address = arr1[arrindex];
abc.style.backgroundImage = `url(${address})`;
abc.classList.remove("fadein");
setTimeout(()=>abc.classList.add("fadein"), 3000);
arrindex++;
}
body {
height:100vh;
}
#picture {
background-repeat: no-repeat;
background-position: center;
background-size: 400px 400px;
width:80%;
margin:auto;
height: 80%;
opacity: 0;
}
#picture.fadein {
opacity: 1;
transition: opacity 2s linear;
}
<body>
<div id="picture"></div>
</body>

Why does website cause most elements to be recalculated upon small change after being hosted?

I decided to make a Pac-Man game and after I did it and everything was working somewhat fine on local document I pushed my website on Github pages and decrease in fps was enormous. It turned out page was making recalculation for hundreds elements which caused 20ms+ delay.
Here's a small part of the code that still has performance difference between local and github-pages hosted website.
const gameBoard = document.getElementById("game-board");
const root = document.documentElement.style;
let elements;
let characterNode;
let position = 658;
makeLevel();
function makeLevel() {
for (let i = 0; i < 868; i++) {
const element = document.createElement("DIV");
element.style.backgroundPosition = `0 0`;
let character = document.createElement("DIV");
character.className = "yellow";
element.append(character);
gameBoard.append(element);
}
elements = Array.from(gameBoard.children);
characterNode = elements[658].children[0];
changePosition();
}
function changePosition() {
root.setProperty(`--yellow-sprite-y`, `-32px`);
characterNode.style.transform = `translateX(-20px)`;
setTimeout(() => {
characterNode.style.transform = "";
characterNode.classList.remove(`yellow-visible`);
position = position - 1;
characterNode = elements[position].children[0];
characterNode.classList.add(`yellow-visible`);
changePosition()
}, 200)
}
:root {
--yellow-sprite-y: -32px;
}
#game-board {
width: 560px;
height: 620px;
display: grid;
grid-template-columns: repeat(28, 20px);
background-color: #000000;
}
#game-board > * {
position: relative;
width: 20px;
height: 20px;
}
.yellow {
position: absolute;
top: -4px;
left: -5.5px;
width: 30px;
height: 28px;
z-index: 10;
}
.yellow-visible {
background-image: url("https://i.imgur.com/SphNpH6.png");
background-position: -32px var(--yellow-sprite-y);
transition: transform 200ms linear;
}
<div id="game-board">
</div>
The exact problem in this code is line 29 which on local document performs like this:
while after hosting it on Github performs this way:
Why is it working this way and what can I do to lessen the performance decrease on hosted page?
Amazingly everything works well and bug doesn't exist on CodePen, yet on Github it still persists.
After getting some feedback that my site works well for other users I shared it on CodePen and it also worked fine, day later somebody said there could be an extension that could do something like that and indeed Adblocker Ultimate caused the slow performance.

Change location of pop-up?

I'm relatively new to this and trying to create a pop-up. I'm not sure how to get the pop-up to be in the middle of the page and still populate the box correctly, since it ends up being inside the table. I tried setting a position in the CSS but that didn't work. Maybe I did it wrong?
PHP
foreach ($updateInfo['updates'] as $update) {
echo "<table><tr><td>";
if (isset($update['details']['newsDetails']['fldDatePosted'])) {
echo '<a class="news_popper">'.$update['details']['newsDetails']['fldDatePosted'].'</a><div class="news_pop"><p>'.$update['details']['newsDetails']['fldBody'].'</p></div>';
}
echo "</td></tr></table>";
}
CSS
.news_pop {
display:none;
position: absolute;
z-index: 99999;
padding: 10px;
background: #ffffff;
border: 1px solid #A2ADBC;
}
JS
$(function() {
$('a.news_popper').click(function() {
$(this).next(".news_pop").toggle();
});
});
I would suggest coding a popup in a more object oriented approach, that way you can call it whenever you need it throughout the page, and you can have multiple instances if needed. What I would do is create a constructor for the popup and a div that manages the pop ups.
First the pop up manager:
const popUpManager = (function popUpManager() {
const $popUpManager = document.createElement('div');
$popUpManager.className = "pop-up_manager";
document.body.append($popUpManager);
return {
createPopUp: () => {
const popup = new Popup();
const $popup = popup.getPopup();
$popUpManager.append($popup);
return popup;
}
}
})();
We create a div called pop-up_manager that will house your popup and allow you to place it where ever you need throughout the page.
Then we need to create the blueprint for what a popup is:
class Popup{
constructor() {
this.$popup = document.createElement('div');
this.$popup.className = 'pop-up';
this.$popup.innerHTML = '<div class="exit-button">X</div><div class="body"></div>';
this.$exitButton = this.$popup.querySelector('.exit-button');
this.$body = this.$popup.querySelector('.body');
this.setUpListeners();
}
getPopup() {
return this.$popup;
}
setContent($content) {
if (typeof $content === 'string') {
this.$body.innerHTML = $content;
} else {
this.$body.appendChild($content);
}
}
Every time we call new Popup(); we will generate a div that floats over the page that we can set to house anything we want by passing content to the setContent() method. This will create what is in the pop up.
Finally, the styling can be configured to whatever you want in the css:
.pop-up {
position: fixed;
height: 300px;
width: 300px;
background-color: grey;
/* Positioning */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.body {
height: 100%;
width: 100%;
}
.exit-button {
cursor: pointer;
}
To call the popup from anywhere in you JS all you have to do is:
$('a.news_popper').click(function() {
const popup = popUpManager.createPopUp();
popup.setContent('<h1>INSERT CONTENT TO SHOW USER HERE</h1>');
});
Here is a codepen: CodePen Link

How to change opacity of element when scrolled to bottom within media query

I just want to ask. I want to make the product image thumbnail in shopify disappear when I scrolled down to bottom of the page, and I want a bit of transition with it.. I really can't figure out how to do this..
Here's my code..
https://jsfiddle.net/vsLdz4qb/1/
function myFunction(screenWidth) {
if (screenWidth.matches) { // If media query matches
window.onscroll = function(ev) {
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
document.getElementByClass("product-single__thumbnails").style.transition = "0.65s";
document.getElementByClass("product-single__thumbnails").style.opacity = 0;
}
};
}
}
let screenWidth = window.matchMedia("(min-width: 750px)");
myFunction(screenWidth); // Call listener function at run time
screenWidth.addListener(myFunction)
Thank you so much in advance!
The correct document method is document.getElementsByClassName and since it returns an array you need the first element of it so change this:
document.getElementByClass("product-single__thumbnails").style.transition = "0.65s";
document.getElementByClass("product-single__thumbnails").style.opacity = 0;
to:
document.getElementsByClassName("product-single__thumbnails")[0].style.transition = "0.65s";
document.getElementsByClassName("product-single__thumbnails")[0].style.opacity = 0;
You can read more about the method here
You should use getElementsByClassName in place of getElementByClass(This is not correct function)
and this will return an array like structure so you need to pass 0 index, if only one class available on page.
or you can try querySelector(".product-single__thumbnails");
and for transition, you can define that in your .product-single__thumbnails class like: transition: opacity .65s linear; - use here which property, you want to animate.
<!-- [product-image] this is for product image scroll down disappear -->
function myFunction(screenWidth) {
if (screenWidth.matches) { // If media query matches
window.onscroll = function(ev) {
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
document.getElementsByClassName("product-single__thumbnails")[0].style.opacity = 0;
}
};
}
}
let screenWidth = window.matchMedia("(min-width: 350px)");
myFunction(screenWidth); // Call listener function at run time
screenWidth.addListener(myFunction)
body {
margin:0;
height: 1000px;
}
.product-single__thumbnails {
background-color: red;
color: white;
width: 50px;
height: 50px;
position: fixed;
transition: opacity .65s linear;
border-radius: 4px;
margin: 20px;
text-align: center;
}
<div class="product-single__thumbnails">
<p>red</p>
</div>

Fading Banner Using `background:url()`

I have a banner enclosed in a div tag that contains my banner. I would like to get the banner to fade to the next image but unsure how to achieve the fading effect. I have tried using jQuery fadeIn() but it failed.
The reason why I need to use the background: url() is because I want this banner image to resize pleasantly when the browser gets resized. I am not sure if this is the best way of approaching my problem.
EDIT - My current code does swap the images in the banner, but does not apply the fadeIn() effect. The console does not report any errors.
CSS:
header div#banner {
background: url(../image/banner/00.jpg) no-repeat center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
height: 300px;
}
JavaScript:
var bannerImages = new Array();
var bannerCounter = 0;
function run() {
loadBannerImages();
runBannerTimer();
}
function loadBannerImages() {
var filePath = "image/banner/";
bannerImages[0] = filePath + "00.jpg";
bannerImages[1] = filePath + "01.jpg";
bannerImages[2] = filePath + "02.jpg";
bannerImages[3] = filePath + "03.jpg";
bannerImages[4] = filePath + "04.jpg";
}
function runBannerTimer() {
var t=setTimeout("swapBannerImage()",2000);
}
function swapBannerImage() {
$('#banner').fadeIn(1000, function() {
$('#banner').css('background', 'url(' + bannerImages[bannerCounter] + ') no-repeat center');
});
bannerCounter++;
if (bannerCounter >= bannerImages.length) {
bannerCounter = 0;
}
runBannerTimer();
}
Your setTimeout isn't correct; try the following instead:
function runBannerTimer() {
var t=setTimeout(function(){
swapBannerImage()
},2000);
}
EDIT
Here is the updated Banner Swap function:
function swapBannerImage() {
$('#banner').fadeOut('slow', function(){
$('#banner').css('background', 'url(' + bannerImages[bannerCounter] + ') no-repeat center').fadeIn('slow');
});
bannerCounter++;
if (bannerCounter >= bannerImages.length) {
bannerCounter = 0;
}
runBannerTimer();
}
Updated Demo Here
You could use multiple divs -- one per image -- and fade them in/out. The divs could still use the css background like you want, you'll just need to absolutely position them, so that they appear one on top of another. However, to get absolutely positioned divs to resize with the parent div (ie to get the "pleasant" resizing effect), you have to set up the css like so:
header div#banner {
... /* your background stuff here */
position: absolute;
left: 0;
right: 0;
height: 300px;
}
Note that you'll assign both left and right, which would make it take up the entire width of the parent. And, make sure that the parent has position:relative.

Categories