I'm having a problem with showing an overlay div element and then hiding it again after the runSearch() function has completed. In short, the overlay does not appear at all.
What the overlay should look like if it worked:
If I had to guess, I believe it could relate to a misunderstanding about how to implement async/await correctly in javascript.
Since I am limited for space here, the full Github project is accessible as a fully deployed page here, if you need more context. However, the most relevant excerpts are below:
The overlay div element in index.html:
<div class="overlay d-flex justify-content-center align-items-center">
<h5>Please wait...</h5>
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
The overlay in CSS:
.overlay {
background-color:#EFEFEF;
position: fixed;
width: 100%;
height: 100%;
z-index: 1000;
left: 0px;
display: none!important;
/* without !important, the overlay would immediately kick into effect */
}
The JS functions which show and hide the overlay when called upon:
function loadingOverlayOn() {
document
.getElementsByClassName("overlay")[0]
.style.display = 'block'
}
function loadingOverlayOff() {
document
.getElementsByClassName("overlay")[0]
.style.display = 'none'
}
JS with respect to button #1:
cityInstanceBtn.addEventListener('click',async function(e){
// for use in headings inside runSearch
// reset
globalCityName === null;
globalCityState === null;
globalCityCountry === null;
globalCityName = e.target.dataset.city
globalCityState = e.target.dataset.state
globalCityCountry = e.target.dataset.country
loadingOverlayOn();
await runSearch(cityName, cityState, cityCountry, cityLat, cityLng, units)
loadingOverlayOff();
})
JS with respect to button #2, which occurs inside of a temporarily displayed Bootstrap modal:
cityInstanceBtn.addEventListener('click', async function(){
myModal.hide()
globalCityName = document.getElementById(id).dataset.city
globalCityState = document.getElementById(id).dataset.state
globalCityCountry = document.getElementById(id).dataset.country
loadingOverlayOn();
await runSearch(cityName, cityState, cityCountry, cityLat, cityLng, units)
loadingOverlayOff();
})
The JS function during which the overlay should be shown, and hidden once its execution is complete:
async function runSearch(
cityName,
cityState,
country,
cityLat,
cityLng,
detectedUnits
) {
console.log("check cityState: " + cityState);
console.log("check globalCityState: " + globalCityState);
var h2Today = document.getElementById("today-title");
var h2Next5Days = document.getElementById("next-5-days-title");
if (globalCityState != "undefined" && globalCityName && globalCityCountry) {
h2Today.innerHTML = `<span class="orange">Today's</span> forecast for <span class="cornflowerblue">${globalCityName}, ${globalCityState}, ${globalCityCountry}</span>`;
h2Next5Days.innerHTML = `<span class="orange">4-day</span> outlook for <span class="cornflowerblue">${globalCityName}, ${globalCityState}, ${globalCityCountry}</span>`;
} else if (
(globalCityState = "undefined" && globalCityName && globalCityCountry)
) {
h2Today.innerHTML = `<span class="orange">Today's</span> forecast for <span class="cornflowerblue">${globalCityName},${globalCityCountry}</span>`;
h2Next5Days.innerHTML = `<span class="orange">4-day</span> outlook for <span class="cornflowerblue">${globalCityName}, ${globalCityCountry}</span>`;
}
var newSearchObject = {
cityName: cityName,
cityState: cityState,
cityCountry: country,
cityLat: cityLat,
cityLng: cityLng,
detectedUnits: detectedUnits,
};
var retrievedLocalStorage = localStorage.getItem("savedCities");
retrievedLocalStorage = JSON.parse(retrievedLocalStorage);
// const arr = retrievedLocalStorage.map(a => {a.cityLat, a.cityLng})
if (retrievedLocalStorage === null) {
localStorage.setItem("savedCities", JSON.stringify([newSearchObject]));
generatePrevCitiesList();
} else if (
retrievedLocalStorage.length > 0 &&
retrievedLocalStorage.length < 5
) {
retrievedLocalStorage.reverse();
if (
!retrievedLocalStorage.some((s) => {
return (
s.cityLat == newSearchObject.cityLat &&
s.cityLng == newSearchObject.cityLng
);
})
) {
// Check if an array of objects contains another object: https://stackoverflow.com/a/63336477/9095603
// this solution which converts objects to string first isn't entirely reliable if you can't guarantee the same order is preserved, for example: https://stackoverflow.com/a/201305/9095603
retrievedLocalStorage.push(newSearchObject);
retrievedLocalStorage.reverse();
console.log("existingSearchObject2: " + retrievedLocalStorage);
localStorage.setItem(
"savedCities",
JSON.stringify(retrievedLocalStorage)
);
}
generatePrevCitiesList();
} else if (retrievedLocalStorage.length >= 5) {
retrievedLocalStorage.reverse();
if (
!retrievedLocalStorage.some((s) => {
return (
s.cityLat == newSearchObject.cityLat &&
s.cityLng == newSearchObject.cityLng
);
})
) {
retrievedLocalStorage.push(newSearchObject);
}
while (retrievedLocalStorage.length > 5) {
retrievedLocalStorage.shift();
}
retrievedLocalStorage.reverse();
localStorage.setItem("savedCities", JSON.stringify(retrievedLocalStorage));
generatePrevCitiesList();
}
fetch(
`https://api.openweathermap.org/data/2.5/forecast?lat=${cityLat}&lon=${cityLng}&units=${detectedUnits}&appid=${apiKey}`
)
.then((response) => response.json())
.then((data) => {
console.log(data);
console.table(data.list);
console.log(JSON.stringify(data));
var timezone = data.city.timezone;
console.log({ timezone });
var country = data.city.country;
console.log({ country });
var cityName = data.city.name;
console.log({ cityName });
var datesArray = [];
console.log({ datesArray });
const days = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
];
// var h2Today = document.getElementById('today-title')
// h2Today.innerHTML = `<span class="orange">Today's</span> forecast for <span class="cornflowerblue">${globalCityName}, ${globalCityState}, ${globalCityCountry}</span>`
// }
// h2Today.innerHTML = `<span class="orange">Today's</span> forecast for <span class="cornflowerblue">${globalCityName},${globalCityCountry}</span>`
// }
for (let i = 0; i < data.list.length; i++) {
var unixTimestamp = data.list[i].dt;
console.log(data.list[i].dt);
// you don't need it for dt_txt but if you want to use the unix timestamp in the data, you can do this conversion:
var jsTimestamp = unixTimestamp * 1000;
var date = new Date(jsTimestamp);
var basicDateLocalAU = date.toLocaleDateString("en-AU");
var basicDateLocalUS = date.toLocaleDateString("en-US");
var basicDateLocalUser = date.toLocaleDateString(`en-${country}`);
console.log(basicDateLocalAU); // Prints: 5/6/2022
console.log(basicDateLocalUS); // Prints: 6/5/2022
console.log(basicDateLocalUser); // Prints: 6/5/2022
var timeLocalAU = date.toLocaleTimeString("en-AU", {
hour: "2-digit",
minute: "2-digit",
}); // Prints: 13:10:34
// https://stackoverflow.com/a/20430558/9095603
// https://bobbyhadz.com/blog/javascript-typeerror-date-getday-is-not-a-function#:~:text=getDay%20is%20not%20a%20function%22%20error%20occurs%20when%20the%20getDay,method%20on%20valid%20date%20objects.
data.list[i].basicDateLocalAU = basicDateLocalAU;
data.list[i].basicDateLocalUS = basicDateLocalUS;
data.list[i].basicDateLocalUser = basicDateLocalUser;
data.list[i].dayOfWeekIndex = date.getDay();
data.list[i].dayOfWeekValue = days[date.getDay()];
data.list[i].basicTime = timeLocalAU;
// https://bobbyhadz.com/blog/javascript-array-push-if-not-exist
if (!datesArray.includes(basicDateLocalUser)) {
datesArray.push(basicDateLocalUser);
var dayOfWeek = days[date.getDay()];
console.log(dayOfWeek);
}
}
console.log({ date });
console.log({ data });
var datalist = data.list;
console.log({ datalist });
var obj = groupBy(datalist, "basicDateLocalAU");
console.log({ obj });
// const result = data.list.group(({ basicCalendarDateAU }) => basicCalendarDateAU);
for (let i = 0; i < obj.length; i++) {
var dayTableEle = document.querySelector(`#day${i} table`);
// var textNode = document.createTextNode(`${dayOfWeekValue}`);
dayTableEle.innerHTML = `<row><th>Time</th><th>Temp</th><th></th><th>Conditions</th><th>Humidity</th><th>Wind speed</th></row>`;
for (let j = 0; j < obj[i].length; j++) {
console.log(obj[i].length);
if (!document.querySelector(`#day${i} h5`).innerText) {
document.querySelector(
`#day${i} h5`
).innerText = `${obj[i][j].dayOfWeekValue}`;
}
if (
!document.querySelector(`#day${i} span#usercountry-dateformat`)
.innerText
) {
document.querySelector(
`#day${i} span#usercountry-dateformat`
).innerText = `${obj[i][j].basicDateLocalUser}`;
}
if (
!document.querySelector(`#day${i} span#AU-dateformat`).innerText
) {
document.querySelector(
`#day${i} span#AU-dateformat`
).innerText = `${obj[i][j].basicDateLocalAU}`;
document
.querySelector(`#day${i} span#AU-dateformat`)
.style.setProperty("display", "none");
}
if (
!document.querySelector(`#day${i} span#US-dateformat`).innerText
) {
document.querySelector(
`#day${i} span#US-dateformat`
).innerText = `${obj[i][j].basicDateLocalUS}`;
document
.querySelector(`#day${i} span#US-dateformat`)
.style.setProperty("display", "none");
}
// var kelvinToCelcius = obj[i][j].main.temp - 273.15;
var tempMetric;
var tempImperial;
var windSpeedImperial;
var windSpeedMetric;
if (units == "metric") {
var tempMetric = obj[i][j].main.temp;
tempMetric = roundedToFixed(tempMetric, 1);
var tempImperial = tempMetric * 1.8 + 32;
tempImperial = roundedToFixed(tempImperial, 1);
var windSpeedMetric = obj[i][j].wind.speed;
windSpeedMetric = roundedToFixed(windSpeedMetric, 1);
var windSpeedImperial = windSpeedMetric * 2.23694;
windSpeedImperial = roundedToFixed(windSpeedImperial, 1);
var metricDisplay = "inline";
var imperialDisplay = "none";
} else if (units == "imperial") {
var tempImperial = obj[i][j].main.temp;
tempImperial = roundedToFixed(tempImperial, 1);
var tempMetric = (tempImperial - 32) / 1.8;
tempMetric = roundedToFixed(tempMetric, 1);
var windSpeedImperial = obj[i][j].wind.speed;
windSpeedImperial = roundedToFixed(windSpeedImperial, 1);
var windSpeedMetric = windSpeedImperial / 2.23694;
windSpeedMetric = roundedToFixed(windSpeedMetric, 1);
var metricDisplay = "none";
var imperialDisplay = "inline";
}
dayTableEle.innerHTML += `
<row>
<td id="tdTime">${obj[i][j].basicTime}</td>
<td id="tdTemp">
<span class="temp-metric metric" style="display:${metricDisplay};">${tempMetric} ${tempUnitsMetric}</span>
<span class="temp-imperial imperial" style="display:${imperialDisplay};">${tempImperial} ${tempUnitsImperial}</span>
</td>
<td><img src="https://openweathermap.org/img/wn/${obj[i][j].weather[0].icon}.png" alt="weather icon"></td>
<td id="tdConditions">${obj[i][j].weather[0].description}</td>
<td id="tdHumidity">${obj[i][j].main.humidity} %</td>
<td id="tdWindSpeed">
<span class="windspeed-metric metric" style="display:${metricDisplay};">${windSpeedMetric} ${windSpeedUnitsMetric}</span>
<span class="windspeed-imperial imperial" style="display:${imperialDisplay};">${windSpeedImperial} ${windSpeedUnitsImperial}</span>
</td>
<td id="tdWindDir"><i style="transform: rotate(${obj[i][j].wind.deg}deg)" class="fa-solid fa-arrow-up"></i></td>
</row>
`;
}
}
});
}
We can see here that the event listener is properly attached - this is true of both buttons but I'll show one here just to be representative:
Full Github project is accessible as a fully deployed page here.
To reiterate, the problem is that the overlay does not appear at all during this sequence of events and I'm seeing page elements prematurely before the page is built:
loadingOverlayOn();
await runSearch(cityName, cityState, cityCountry, cityLat, cityLng, units)
loadingOverlayOff();
You are not awaiting fetch, you are using then instead.
You have to await fetch
See below example
const response = await fetch(url);
const jsonData = await response.json()
Issues
I am building a card builder app and the builder is split into three sections; the create (user enters details), the builder (using vue.draggable user can drag stamps on to card) and the preview (card is displayed to user).
I use jQuery to fade each section in and out and I want to increase the speed of the loading time - my issues is that when the build section is first loaded in, it takes a long time, but then it works as expected.
Failed Solutions
I first thought that is was the png stamp images that were increasing the loading time and so I uploaded them to compress.io and this decreased the image sizes from 406KB to 82KB
I then research some solutions and tried compressing the jQuery the original file looks like this:
$(document).ready(function () {
let btn1 = $('#btn-1')
let btn2 = $('#btn-2')
let btn3 = $('#btn-3')
let btn1Txt = $('#btn-1-txt')
let btn2Txt = $('#btn-2-txt')
let btn3Txt = $('#btn-3-txt')
let create = $('.create-container')
let build = $('.build-container')
let preview = $('.preview-container')
let cardTitle
let cardDescription
let logoAlign
let logoShape
let cardSlots
let cardColour
btn1.addClass('active-btn')
btn1Txt.addClass('active-txt')
create.fadeIn(250)
btn1.click(function () {
btn1.addClass('active-btn')
btn1Txt.addClass('active-txt')
btn2.removeClass('active-btn')
btn2Txt.removeClass('active-txt')
btn3.removeClass('active-btn')
btn3Txt.removeClass('active-txt')
build.fadeOut(100)
preview.fadeOut(100)
create.delay(250).fadeIn(100)
});
btn2.click(function () {
btn2.addClass('active-btn')
btn2Txt.addClass('active-txt')
btn1.removeClass('active-btn')
btn1Txt.removeClass('active-txt')
btn3.removeClass('active-btn')
btn3Txt.removeClass('active-txt')
create.fadeOut(100)
preview.fadeOut(100)
build.delay(250).fadeIn(100)
});
btn3.click(function () {
btn3.addClass('active-btn')
btn3Txt.addClass('active-txt')
btn1.removeClass('active-btn')
btn1Txt.removeClass('active-txt')
btn2.removeClass('active-btn')
btn2Txt.removeClass('active-txt')
create.fadeOut(100)
build.fadeOut(100)
preview.delay(250).fadeIn(100)
});
let titleHelper = $('#title-helper')
let titleHelpShow = $('#title-helper-show')
let titleHelpHide = $('#title-helper-close')
let titleInput = $('#title-input')
let descHelper = $('#desc-helper')
let descHelpShow = $('#desc-helper-show')
let descHelpHide = $('#desc-helper-close')
let descInput = $('#desc-input')
let logoHelper = $('#logo-helper')
let logoHelpShow = $('#logo-helper-show')
let logoHelpHide = $('#logo-helper-close')
let logoShapeHelper = $('#logo-shape-helper')
let logoShapeHelpShow = $('#logo-shape-helper-show')
let logoShapeHelpHide = $('#logo-shape-helper-close')
let colourHelper = $('#colour-helper')
let colourHelpShow = $('#colour-helper-show')
let colourHelpHide = $('#colour-helper-close')
let colourInput = $('#colour-input')
let numHelper = $('#num-helper')
let numHelpShow = $('#num-helper-show')
let numHelpHide = $('#num-helper-close')
let numInput = $('#num-input')
let alignLeft = $('#align-left-opt')
let alignCenter = $('#align-center-opt')
let alignRight = $('#align-right-opt')
let circleLogo = $('#circle-logo')
let squareLogo = $('#square-logo')
let stamp5 = $('#stamps-5')
let stamp10 = $('#stamps-10')
let stamp15 = $('#stamps-15')
let colourPicker = $('#colour-input')
titleHelpShow.click(function() {titleHelper.fadeIn(200)});
titleHelpHide.click(function() {titleHelper.fadeOut(200)});
titleInput.click(function() {titleHelper.fadeOut(200)});
descHelpShow.click(function() {descHelper.fadeIn(200)});
descHelpHide.click(function() {descHelper.fadeOut(200)});
descInput.click(function() {descHelper.fadeOut(200)});
logoHelpShow.click(function() {logoHelper.fadeIn(200)});
logoHelpHide.click(function() {logoHelper.fadeOut(200)});
alignLeft.click(function() {logoHelper.fadeOut(200)});
alignCenter.click(function() {logoHelper.fadeOut(200)});
alignRight.click(function() {logoHelper.fadeOut(200)});
logoShapeHelpShow.click(function() {logoShapeHelper.fadeIn(200)});
logoShapeHelpHide.click(function() {logoShapeHelper.fadeOut(200)});
circleLogo.click(function() {logoShapeHelper.fadeOut(200)});
squareLogo.click(function() {logoShapeHelper.fadeOut(200)});
numHelpShow.click(function() {numHelper.fadeIn(200)});
numHelpHide.click(function() {numHelper.fadeOut(200)});
numInput.click(function() {numHelper.fadeOut(200)});
stamp5.click(function() {numHelper.fadeOut(200)});
stamp10.click(function() {numHelper.fadeOut(200)});
stamp15.click(function() {numHelper.fadeOut(200)});
colourHelpShow.click(function() {colourHelper.fadeIn(200)});
colourHelpHide.click(function() {colourHelper.fadeOut(200)});
colourInput.click(function() {colourHelper.fadeOut(200)});
alignLeft.click(function() {
alignRight.removeClass('active-btn')
alignCenter.removeClass('active-btn')
alignLeft.addClass('active-btn')
});
alignCenter.click(function () {
alignRight.removeClass('active-btn')
alignLeft.removeClass('active-btn')
alignCenter.addClass('active-btn')
});
alignRight.click(function () {
alignLeft.removeClass('active-btn')
alignCenter.removeClass('active-btn')
alignRight.addClass('active-btn')
});
circleLogo.click(function () {
squareLogo.removeClass('active-btn')
circleLogo.addClass('active-btn')
});
squareLogo.click(function () {
circleLogo.removeClass('active-btn')
squareLogo.addClass('active-btn')
});
stamp5.click(function () {
stamp10.removeClass('active-btn')
stamp15.removeClass('active-btn')
stamp5.addClass('active-btn')
});
stamp10.click(function () {
stamp5.removeClass('active-btn')
stamp15.removeClass('active-btn')
stamp10.addClass('active-btn')
});
stamp15.click(function () {
stamp10.removeClass('active-btn')
stamp5.removeClass('active-btn')
stamp15.addClass('active-btn')
});
cardTitle = "Untitled Card"
cardDescription = "This is the card Description"
logoAlign = "Left"
logoShape = "Square"
cardSlots = 5
cardColour = colourPicker.val()
titleInput.change(function() {cardTitle = titleInput.val()});
descInput.change(function() {cardDescription = descInput.val()});
alignLeft.click(function() {logoAlign = "Left"});
alignCenter.click(function() {logoAlign = "Center"});
alignRight.click(function() {logoAlign = "Right"});
circleLogo.click(function() {logoShape = "Circle"});
squareLogo.click(function() {logoShape = "Square"});
stamp5.click(function () {cardSlots = 5});
stamp10.click(function () {cardSlots = 10});
stamp15.click(function () {cardSlots = 15});
colourPicker.change(function() {cardColour = colourPicker.val()});
let logo = $('.sample-logo-container')
let logoPosition = $('.logo-align-container')
let cardHolder = $('.builder-card')
let stampRow1 = $('#stamp-row-1')
let stampRow2 = $('#stamp-row-2')
let stampRow3 = $('#stamp-row-3')
btn2.click(function () {
console.log("Title: " + cardTitle)
console.log("Description: " + cardDescription)
console.log("Logo Alignment: " + logoAlign)
console.log("Logo Shape: " + logoShape)
console.log("Num of stamps: " + cardSlots)
console.log("Background Colour: " + cardColour)
if (logoShape === "Square") {
logo.removeClass('circle-logo')
logo.addClass('square-logo')
}
if (logoShape === "Circle") {
logo.removeClass('square-logo')
logo.addClass('circle-logo')
}
if (logoAlign === "Left") {
logoPosition.removeClass('logo-align-middle')
logoPosition.removeClass('logo-align-right')
logo.removeClass('logo-align-middle')
logo.removeClass('m-inline-e')
logoPosition.addClass('logo-align-left')
logo.addClass('m-inline-s')
}
if (logoAlign === "Center") {
logoPosition.removeClass('logo-align-left')
logoPosition.removeClass('logo-align-right')
logo.removeClass('m-inline-s')
logo.removeClass('m-inline-e')
logoPosition.addClass('logo-align-middle')
logo.addClass('logo-align-middle')
}
if (logoAlign === "Right") {
logoPosition.removeClass('logo-align-left')
logoPosition.removeClass('logo-align-middle')
logo.removeClass('m-inline-s')
logo.removeClass('logo-align-middle')
logoPosition.addClass('logo-align-right')
logo.addClass('m-inline-e')
}
if (cardSlots === 5) {
stampRow1.show()
stampRow2.hide()
stampRow3.hide()
cardHolder.removeClass('two-stamp-row-height')
cardHolder.removeClass('three-stamp-row-height')
cardHolder.addClass('one-stamp-row-height')
}
if (cardSlots === 10) {
stampRow1.show()
stampRow2.show()
stampRow3.hide()
cardHolder.removeClass('one-stamp-row-height')
cardHolder.removeClass('three-stamp-row-height')
cardHolder.addClass('two-stamp-row-height')
}
if (cardSlots === 15) {
stampRow1.show()
stampRow2.show()
stampRow3.show()
cardHolder.removeClass('one-stamp-row-height')
cardHolder.removeClass('two-stamp-row-height')
cardHolder.addClass('three-stamp-row-height')
}
cardHolder.css("background-color", cardColour)
});
});
And the compressed file looks like this:
$(document).ready(function(){let e=$("#btn-1"),t=$("#btn-2"),l=$("#btn-3"),a=$("#btn-1-txt"),o=$("#btn-2-txt"),c=$("#btn-3-txt"),i=$(".create-container"),n=$(".build-container"),s=$(".preview-container"),d,r,u,v,f,m;e.addClass("active-btn"),a.addClass("active-txt"),i.fadeIn(250),e.click(function(){e.addClass("active-btn"),a.addClass("active-txt"),t.removeClass("active-btn"),o.removeClass("active-txt"),l.removeClass("active-btn"),c.removeClass("active-txt"),n.fadeOut(100),s.fadeOut(100),i.delay(250).fadeIn(100)}),t.click(function(){t.addClass("active-btn"),o.addClass("active-txt"),e.removeClass("active-btn"),a.removeClass("active-txt"),l.removeClass("active-btn"),c.removeClass("active-txt"),i.fadeOut(100),s.fadeOut(100),n.delay(250).fadeIn(100)}),l.click(function(){l.addClass("active-btn"),c.addClass("active-txt"),e.removeClass("active-btn"),a.removeClass("active-txt"),t.removeClass("active-btn"),o.removeClass("active-txt"),i.fadeOut(100),n.fadeOut(100),s.delay(250).fadeIn(100)});let C=$("#title-helper"),g=$("#title-helper-show"),h=$("#title-helper-close"),p=$("#title-input"),k=$("#desc-helper"),b=$("#desc-helper-show"),w=$("#desc-helper-close"),O=$("#desc-input"),x=$("#logo-helper"),I=$("#logo-helper-show"),q=$("#logo-helper-close"),L=$("#logo-shape-helper"),y=$("#logo-shape-helper-show"),S=$("#logo-shape-helper-close"),D=$("#colour-helper"),R=$("#colour-helper-show"),T=$("#colour-helper-close"),A=$("#colour-input"),B=$("#num-helper"),N=$("#num-helper-show"),U=$("#num-helper-close"),j=$("#num-input"),z=$("#align-left-opt"),E=$("#align-center-opt"),F=$("#align-right-opt"),G=$("#circle-logo"),H=$("#square-logo"),J=$("#stamps-5"),K=$("#stamps-10"),M=$("#stamps-15"),P=$("#colour-input");g.click(function(){C.fadeIn(200)}),h.click(function(){C.fadeOut(200)}),p.click(function(){C.fadeOut(200)}),b.click(function(){k.fadeIn(200)}),w.click(function(){k.fadeOut(200)}),O.click(function(){k.fadeOut(200)}),I.click(function(){x.fadeIn(200)}),q.click(function(){x.fadeOut(200)}),z.click(function(){x.fadeOut(200)}),E.click(function(){x.fadeOut(200)}),F.click(function(){x.fadeOut(200)}),y.click(function(){L.fadeIn(200)}),S.click(function(){L.fadeOut(200)}),G.click(function(){L.fadeOut(200)}),H.click(function(){L.fadeOut(200)}),N.click(function(){B.fadeIn(200)}),U.click(function(){B.fadeOut(200)}),j.click(function(){B.fadeOut(200)}),J.click(function(){B.fadeOut(200)}),K.click(function(){B.fadeOut(200)}),M.click(function(){B.fadeOut(200)}),R.click(function(){D.fadeIn(200)}),T.click(function(){D.fadeOut(200)}),A.click(function(){D.fadeOut(200)}),z.click(function(){F.removeClass("active-btn"),E.removeClass("active-btn"),z.addClass("active-btn")}),E.click(function(){F.removeClass("active-btn"),z.removeClass("active-btn"),E.addClass("active-btn")}),F.click(function(){z.removeClass("active-btn"),E.removeClass("active-btn"),F.addClass("active-btn")}),G.click(function(){H.removeClass("active-btn"),G.addClass("active-btn")}),H.click(function(){G.removeClass("active-btn"),H.addClass("active-btn")}),J.click(function(){K.removeClass("active-btn"),M.removeClass("active-btn"),J.addClass("active-btn")}),K.click(function(){J.removeClass("active-btn"),M.removeClass("active-btn"),K.addClass("active-btn")}),M.click(function(){K.removeClass("active-btn"),J.removeClass("active-btn"),M.addClass("active-btn")}),d="Untitled Card",r="This is the card Description",u="Left",v="Square",f=5,m=P.val(),p.change(function(){d=p.val()}),O.change(function(){r=O.val()}),z.click(function(){u="Left"}),E.click(function(){u="Center"}),F.click(function(){u="Right"}),G.click(function(){v="Circle"}),H.click(function(){v="Square"}),J.click(function(){f=5}),K.click(function(){f=10}),M.click(function(){f=15}),P.change(function(){m=P.val()});let Q=$(".sample-logo-container"),V=$(".logo-align-container"),W=$(".builder-card"),X=$("#stamp-row-1"),Y=$("#stamp-row-2"),Z=$("#stamp-row-3");t.click(function(){console.log("Title: "+d),console.log("Description: "+r),console.log("Logo Alignment: "+u),console.log("Logo Shape: "+v),console.log("Num of stamps: "+f),console.log("Background Colour: "+m),"Square"===v&&(Q.removeClass("circle-logo"),Q.addClass("square-logo")),"Circle"===v&&(Q.removeClass("square-logo"),Q.addClass("circle-logo")),"Left"===u&&(V.removeClass("logo-align-middle"),V.removeClass("logo-align-right"),Q.removeClass("logo-align-middle"),Q.removeClass("m-inline-e"),V.addClass("logo-align-left"),Q.addClass("m-inline-s")),"Center"===u&&(V.removeClass("logo-align-left"),V.removeClass("logo-align-right"),Q.removeClass("m-inline-s"),Q.removeClass("m-inline-e"),V.addClass("logo-align-middle"),Q.addClass("logo-align-middle")),"Right"===u&&(V.removeClass("logo-align-left"),V.removeClass("logo-align-middle"),Q.removeClass("m-inline-s"),Q.removeClass("logo-align-middle"),V.addClass("logo-align-right"),Q.addClass("m-inline-e")),5===f&&(X.show(),Y.hide(),Z.hide(),W.removeClass("two-stamp-row-height"),W.removeClass("three-stamp-row-height"),W.addClass("one-stamp-row-height")),10===f&&(X.show(),Y.show(),Z.hide(),W.removeClass("one-stamp-row-height"),W.removeClass("three-stamp-row-height"),W.addClass("two-stamp-row-height")),15===f&&(X.show(),Y.show(),Z.show(),W.removeClass("one-stamp-row-height"),W.removeClass("two-stamp-row-height"),W.addClass("three-stamp-row-height")),W.css("background-color",m)})});
Video of problem
Loading time is slow because of screen recording
https://imgur.com/a/XcFXXKJ
Hi everyone I am currently stuck trying to debug my program. MY goal is for whenever the button "Start Animation" is clicked, the web page displays an animated times table according to the number that the user enters in the text field in the following manner. For example, if the user entered the number 6 in the text field, then the animation displays 1 x 6 = 6, one second later it replaces it with 2 x 6 = 12, one second later it replaces it with 3 x 6 = 18, etc. If it is 9 x 6 = 54, then one second later it becomes 1 x 6 = 6, and then 2 x 6 = 12, and so on.
var counter;
var animationOn = false;
var counterAnimation;
function updateAnimation() {
var value = document.getElementById('value1').value;
for (var i = 1; i < 1000; i++) {
for (var j = 1; j < 10; j++) {
var product = j * value;
var counterSpan = document.getElementById("counterHolder");
counterSpan.innerHTML = product;
}
}
counterAnimation = setTimeout(updateAnimation, 1000);
}
function startAnimation() {
if (animationOn == false) {
animationOn = true;
counter = 1;
counterAnimation = setTimeout(updateAnimation, 1000);
}
}
function stopAnimation() {
if (animationOn == true) {
animationOn = false;
clearTimeout(updateAnimation);
}
}
<body>
<button onclick="startAnimation();">
Start animation
</button>
<button onclick="stopAnimation();">
Stop animation
</button><br><br>
<label>Enter an integer: </label>
<input type="number" size=20 id=value1 name="value">
<span id="counterHolder">0</span>
</body>
Edited
Here is a complete solution which makes changes displayed value by time
let counter;
let animationOn = false;
let counterAnimation;
let mult = 1;
function updateAnimation() {
let value = document.getElementById('value1').value;
let counterSpan = document.getElementById("counterHolder");
if (mult >= 10) {
mult = 1;
counter = null;
animationOn = false;
counterAnimation = null;
counterSpan.innerHTML = 0;
return;
}
let product = mult * value;
counterSpan.innerHTML = product;
mult++
counterAnimation = setTimeout(updateAnimation, 1000)
}
function startAnimation() {
if (!animationOn)
{
animationOn = true;
counter = 1;
counterAnimation = setTimeout(updateAnimation, 1000);
}
}
function stopAnimation() {
if (animationOn)
{
animationOn = false;
clearTimeout(counterAnimation);
mult = 1
counter = null
animationOn = false
counterAnimation = null
}
}
<body>
<button onclick="startAnimation();">
Start animation
</button>
<button onclick="stopAnimation();">
Stop animation
</button><br><br>
<label>Enter an integer: </label>
<input type="number" size=20 id=value1 name="value">
<span id="counterHolder">0</span>
</body>
I have managed to dynamically display the sum of 6 line-cost DOM elements from a php file. Unfortunately, when trying to calculate the delivery charge, my JavaScript methods regarding to the deliveryCharge implementation fails to display anything on the page. With the sub-total methods working and displaying perfectly, I tried to troubleshoot the problem by providing innerHTML with a constant value of both a string and an int- both times yielded nothing to be displayed on screen.
I have displayed both the working part of the sub-total calculation method as well as the non-working part of the delivery-charge calculation. Would the problem lie within an incorrect way of using innerHTML, be a calculation error or a different error entirely?
function calcST(){
var i;
var sum = 0; // initialize the sum
let p = document.getElementsByTagName("line_cost");
for (i = 0; i < p.length; i++) {
if (!isNaN(Number(p[i].innerHTML))) {
sum = Number(sum + Number(p[i].innerHTML)); // p[i].innerHTML gives you the value
}
}
setST(sum, "sub_total");
}
function setST(sum, item_id){
let i = document.getElementById(item_id);
i.innerHTML = sum;
calcDelivCharge();
}
function getST() {
let i = document.getElementById("sub_total");
let v = i.innerHTML;
return v;
}
function calcDelivCharge(){
var delCharge;
var e = getST();
if(e < 100){
delcharge = e*0.10
}else{
delcharge = 0;
}
setDelivCharge("delivery_charge", delCharge);
}
function setDelivCharge(item_id, delCharge){
let i = document.getElementById(item_id);
i.innerHTML = delCharge;
calculateTAX();
}
function getDelivCharge() {
let i = document.getElementById("delivery_charge");
let v = i.innerHTML;
return v;
}
I managed to find that the DOM was not ready loading before the getST() method was called. This can be fixed with the following code:
if(document.getElementById("sub_total") != null){
let i = document.getElementById("sub_total");
let v = i.innerHTML;
return v;
}
Unfortunately, delivery-charge is seen as 'unidentified'. Why does this appear when the getST() method is altered?
Well, if you're HTML is like
<line_cost>
<div>30</div>
<div>40</div>
...
</line_cost>
You can do this:
function calcSubtotal() {
const costs = document.querySelector("line_cost").children;
let sum = 0;
for( let i = 0 ; i < costs.length ; i ++) {
sum += parseInt(costs[i].innerHTML);
}
setST(sum, "sub_total");
}
// Subtotal getter and setter
function setST(sum, item_id) {
document.getElementById(item_id).innerHTML = sum.toFixed(2);
calcDeliveryCharge();
}
function getSubTotal() {
return document.getElementById("sub_total").innerHTML;
}
function calcDeliveryCharge() {
const subTotal = getSubTotal();
setDeliveryCharge("delivery_charge", subTotal < 100 ? subTotal * 0.10 : 0);
}
function setDeliveryCharge(item_id, deliveryCharge){
document.getElementById(item_id).innerHTML = deliveryCharge.toFixed(2);
//calculateTAX();
}
function getDeliveryCharge() {
return document.getElementById("delivery_charge").innerHTML;
}
calcSubtotal();
calcDeliveryCharge();
<line_cost>
<div>5</div>
<div>4</div>
<div>3</div>
<div>20</div>
</line_cost>
<br/>
<div>
<span>Sub Total: $
<span id="sub_total"></span>
</span>
<br/>
<span>Delivery Charge: $
<span id="delivery_charge"></span>
</span>
</div>
Otherwise, if you have:
<div>
<line_cost>30</line_cost>
<line_cost>40</line_cost>
...
</div>
Then do this:
function calcSubtotal() {
const costs = document.querySelectorAll("line_cost");
let sum = 0
for( let i = 0 ; i < costs.length ; i ++) {
sum += parseFloat(costs[i].innerHTML);
}
setST(sum, "sub_total");
}
// Subtotal getter and setter
function setST(sum, item_id) {
document.getElementById(item_id).innerHTML = sum.toFixed(2);
calcDeliveryCharge();
}
function getSubTotal() {
return document.getElementById("sub_total").innerHTML;
}
function calcDeliveryCharge() {
const subTotal = getSubTotal();
setDeliveryCharge("delivery_charge", subTotal < 100 ? subTotal * 0.10 : 0);
}
function setDeliveryCharge(item_id, deliveryCharge){
document.getElementById(item_id).innerHTML = deliveryCharge.toFixed(2);
//calculateTAX();
}
function getDeliveryCharge() {
return document.getElementById("delivery_charge").innerHTML;
}
calcSubtotal();
calcDeliveryCharge();
line_cost {
display: block;
}
<div>
<line_cost>25</line_cost>
<line_cost>34</line_cost>
<line_cost>43</line_cost>
<line_cost>250</line_cost>
</div>
<br/>
<div>
<span>Sub Total: $
<span id="sub_total"></span>
</span>
<br/>
<span>Delivery Charge: $
<span id="delivery_charge"></span>
</span>
</div>