How can I decrease loading time of scripts in vue.js? - javascript

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

Related

Async/await function to show, wait, hide overlay not working in javascript

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()

Interact between values

I'm wondering how to stop counting money (iloscPieniedzy) when HP (iloscZycia) is 0 in this code:
let iloscZycia = 20;
const sumaZycia = document.getElementById("suma-zycia");
const dodajZycie = document.getElementById('dodaj-zycie');
const odejmijZycie = document.getElementById('odejmij-zycie');
dodajZycie.addEventListener("click", function() {
iloscZycia++;
sumaZycia.textContent = iloscZycia;
});
odejmijZycie.addEventListener("click", function() {
iloscZycia = iloscZycia - 5;
if (iloscZycia <= 0) {
iloscZycia = 0
};
sumaZycia.textContent = iloscZycia;
});
let iloscPieniedzy = 0;
const sumaPieniedzy = document.getElementById("suma-pieniedzy");
const dodajPieniadze = document.getElementById('dodaj-pieniadze');
const odejmijPieniadze = document.getElementById('odejmij-pieniadze');
dodajPieniadze.addEventListener("click", function() {
iloscPieniedzy = iloscPieniedzy + 10;
sumaPieniedzy.textContent = iloscPieniedzy;
});
odejmijPieniadze.addEventListener("click", function() {
iloscPieniedzy = iloscPieniedzy - 1;
if (iloscPieniedzy <= 0) {
iloscPieniedzy = 0
};
sumaPieniedzy.textContent = iloscPieniedzy;
});
I tried something like this:
if (sumaZycia=0){
sumaPieniedzy=0
};
but even this doesn't work like it's not connected.
the = operator is used to assign values to variables what you're looking for is the equality operator ===.
so try it like this:
if (iloscZycia === 0){
iloscPieniedzy = 0
};
Because Stack Overflow is an English language site, I've renamed your variables and created a map of the new names to previous names in comments at the top of the JavaScript below.
If you create a functional closure for updating your numeric variables, you can encapsulate the necessary logic for only updating money when hp is not equal to 0.
Here's a working example in a code snippet:
// hp: iloscZycia
// element1: sumaZycia
// element2: dodajZycie
// element3: odejmijZycie
// money: iloscPieniedzy
// element4: sumaPieniedzy
// element5: dodajPieniadze
// element6: odejmijPieniadze
let hp = 20;
const adjustHp = (amount) => {
hp += amount;
if (hp < 0) hp = 0;
element1.textContent = hp;
};
const element1 = document.getElementById("suma-zycia");
const element2 = document.getElementById("dodaj-zycie");
const element3 = document.getElementById("odejmij-zycie");
element1.textContent = hp;
element2.addEventListener("click", () => adjustHp(1));
element3.addEventListener("click", () => adjustHp(-5));
let money = 0;
const adjustMoney = (amount) => {
// Update money, but ONLY if hp is not 0:
if (hp !== 0) {
money += amount;
if (money < 0) money = 0;
}
element4.textContent = money;
};
const element4 = document.getElementById("suma-pieniedzy");
const element5 = document.getElementById("dodaj-pieniadze");
const element6 = document.getElementById("odejmij-pieniadze");
element4.textContent = money;
element5.addEventListener("click", () => adjustMoney(10));
element6.addEventListener("click", () => adjustMoney(-1));
.group { display: flex; gap: 0.5rem; }
<h2>HP</h2>
<div class="group">
<button id="odejmij-zycie">-</button>
<div id="suma-zycia">0</div>
<button id="dodaj-zycie">+</button>
</div>
<h2>Money</h2>
<div class="group">
<button id="odejmij-pieniadze">-</button>
<div id="suma-pieniedzy">0</div>
<button id="dodaj-pieniadze">+</button>
</div>

HTML elements becoming unused when I try to connect mongoDB with my JS file

I was working on a code where I fetch and display data from an API. I used to store it in Localstorage of browser's port.But now I wish to connect it to mongoDB.
When I import mongoclient my HTML elements become unused and their reference points nowhere.
This is the Script.js file
const searchInput = document.getElementById('searchInput')
const searchBtn = document.getElementById('searchBtn')
const moviesList = document.getElementById('moviesList')
const watchlist = document.getElementById('watchlist')
const removeWatchlistBtn = document.getElementsByClassName('remove-watchlist-btn')
const cardWatchlistBtn = document.getElementsByClassName('watchlist-btn')
const readMore = document.getElementsByClassName('read-more')
const readMorePlot = document.getElementsByClassName('read-more-plot')
const movieKey = document.getElementsByClassName('movie-key')
const localStorageKeys = Object.keys(localStorage)
if (searchBtn) {
searchBtn.addEventListener('click', searchMovies)
}
async function searchMovies() {
// Hide default elements
if (moviesList.children) {
let children = moviesList.children
let childrenArr = Array.prototype.slice.call(children)
childrenArr.forEach((child) => child.remove())
}
let res = await fetch(`https://www.omdbapi.com/?s=${searchInput.value.trim()}&apikey=e668e570`)
let data = await res.json()
const movies = data.Search
// Get and display search results
movies.forEach(async (movie) => {
let response = await fetch(`https://www.omdbapi.com/?i=${movie.imdbID}&apikey=e668e570`)
let moviesListData = await response.json()
console.log(moviesListData)
const readMoreMovieID = moviesListData.imdbID + 'more'
const hideReadMore = moviesListData.imdbID + 'hide'
const summaryPlot = `${moviesListData.Plot.substring(0, 110)}<span id=${hideReadMore}>...<button class="black read-more" onclick="showCompletePlot(${readMoreMovieID}, ${hideReadMore})">Read more</button></span>`
const readMorePlot = `<span class="read-more-plot" id=${readMoreMovieID} >${moviesListData.Plot.substring(110, moviesListData.Plot.length)}</span>`
const completePlot = moviesListData.Plot
const longPlot = summaryPlot + readMorePlot
const movieID = moviesListData.imdbID
const movieIDkey = moviesListData.imdbID + 'key'
const watchlistBtnKey = moviesListData.imdbID + 'watchlistBtn'
const removeBtnKey = moviesListData.imdbID + 'removeBtn'
moviesList.innerHTML += `
<div class="cards">
<div class="card" id=${movieID}>
<span id=${movieIDkey} class="hide movie-key">${movieIDkey}</span>
<img src=${moviesListData.Poster} class="card-poster" />
<div class="card-header">
<h2 class="card-title">${moviesListData.Title}</h2>
<img src="images/star-icon.svg" class="star-icon" />
<span class="card-rating">${moviesListData.imdbRating}</span>
</div>
<div class="card-meta">
<span class="card-runtime">${moviesListData.Runtime}</span>
<span>${moviesListData.Genre}</span>
<button class="card-btn card-watchlist watchlist-btn" id="${watchlistBtnKey}" onclick="addToWatchlist(${movieIDkey}, ${movieID}, ${watchlistBtnKey}, ${removeBtnKey})"><img src="images/watchlist-icon.svg" alt="Add film to watchlist" class="card-watchlist-plus-icon" /> Watchlist</button>
<button class="card-btn card-watchlist remove-watchlist-btn" id="${removeBtnKey}" onclick="removeFromWatchlist(${movieIDkey}, ${removeBtnKey}, ${watchlistBtnKey}, ${removeBtnKey})"><img src="images/remove-icon.svg" alt="Remove film to watchlist" class="card-watchlist-plus-icon" /> Remove</button>
</div>
<p class="card-plot">${completePlot.length < 110 ? completePlot : longPlot}</p>
</div>
</div>
`
displayWatchlistOrRemoveBtn()
})
}
function displayWatchlistOrRemoveBtn() {
for (let movie of movieKey) {
const removeBtnID = movie.id.slice(0, 9) + 'removeBtn'
const removeBtn = document.getElementById(removeBtnID)
const watchlistBtnID = movie.id.slice(0, 9) + 'watchlistBtn'
const watchlistBtn = document.getElementById(watchlistBtnID)
localStorageKeys.forEach((key) => {
if (movie.id === key) {
removeBtn.style.display = 'inline'
watchlistBtn.style.display = 'none'
}
})
}
}
function showCompletePlot(readMoreMovieID, hideReadMore) {
readMoreMovieID.style.display = 'inline'
hideReadMore.style.display = 'none'
}
async function addToWatchlist(movieIDkey, movieID, watchlistBtnKey, removeBtnKey) {
console.log(movieID.id)
const a = movieID.id
const b= movieID.Title
let sanket = await fetch(`https://www.omdbapi.com/?i=${movieID.id}&apikey=e668e570`)
const ab = await sanket.json()
console.log(ab)
localStorage.setItem(movieIDkey.innerHTML, movieID.innerHTML)
watchlistBtnKey.style.display = 'none'
removeBtnKey.style.display = 'inline'
}
function removeFromWatchlist(movieIDkey, watchlistBtnKey, removeBtnKey) {
localStorage.removeItem(movieIDkey.innerHTML)
// Get parent element (the movie card div) and remove it
if (watchlist) {
localStorage.removeItem(movieIDkey.innerHTML)
const parentEl = document.getElementById(movieIDkey.innerHTML).parentElement
parentEl.remove()
}
watchlistBtnKey.style.display = 'inline'
removeBtnKey.style.display = 'none'
// Display default elements if local storage empty
if (watchlist && localStorage.length === 0) {
if (watchlist.children) {
const children = watchlist.children
const childrenArr = Array.prototype.slice.call(children)
childrenArr.forEach((child) => (child.style.display = 'flex'))
}
}
}
// Hide default elements if data is in local storage
if (watchlist && localStorage.length > 0) {
if (watchlist.children) {
const children = watchlist.children
const childrenArr = Array.prototype.slice.call(children)
childrenArr.forEach((child) => (child.style.display = 'none'))
}
}
for (let i = 0; i < localStorage.length; i++) {
const getLocalStorage = localStorage.getItem(localStorage.key(i))
// Display every key's value to the watchlist
if (watchlist) {
watchlist.innerHTML += `<div class="card">${getLocalStorage}</div>`
// Hide the 'add to watchlist' button
for (let button of cardWatchlistBtn) {
button.style.display = 'none'
}
// Display the 'remove from watchlist' button
for (let button of removeWatchlistBtn) {
button.style.display = 'inline'
}
}
}
Here when I use const { MongoClient } = require("mongodb"); the elements readMore and readMorePlot (Line no.7 and 8) become unused.
I tried exporting my addToWatchlist function but problem persists.
I also have tried adding Type=Module in html file but that doesn't work.

Bokeh Tap tool as trigger callback for different figure

I am trying to use the taptool indices to trigger a callback to another plot/figure.
I adapted my data to fit few examples I have found online as I suck in JS.
I have been stuck for a good while, so any help would be very helpful. I tried to simply the code and unfortunately I can not share the data, but I believe that the code below it is very straightforward.
I am getting a warning that a warning for this line of code below:
wP.select(tap).callback = CustomJS(args = {'week': wP, 'yCol': yCol}, code = code)
'generator' object has no attribute 'callback'
df = YearlyDF_var('Precipitation', 'median')
y = 2020
p1 = figure(match_aspect=True, x_axis_location = None, y_axis_location = None, title='Kalimantan Central',
tools = 'pan, wheel_zoom, box_zoom, reset, save, tap', title_location='below', toolbar_location='above',
plot_height=550)
src = ColumnDataSource(data=df)
for1 = PrintfTickFormatter(format='%0.0f mm')
p1.image_url(url=['BaritoLine3.png'], x=114.368, y=-1.97, w=1.1, h=3.04, anchor="center")
t2 = p1.circle('x', 'y', line_color='black', size=30, alpha=.7, line_width=.5, color='c', muted_alpha=0.3, source=src)
p1.add_layout(t2)
hvF = HoverTool()
hvF.tooltips=[('Collection', '#Location'), ('', '#2020{0.00 a} mm')]
p1.add_tools(hvF)
p1.grid.grid_line_color=None
p1.outline_line_color=None
p1.title.text_font_style = 'bold'
p1.title.text_font_size = '25px'
p1.title.text_color = Viridis[11][3]
p1.title.align = 'center'
p1.toolbar.autohide = True
df1 = pd.DataFrame()
df1 = dfW1.iloc[dfW1.index.get_level_values('yearRaw') == 2020][['Precipitation']]
#dfY = df[[str(var)]]
df2 = pd.DataFrame()
df2[['week', 'Muara_Teweh', 'Muara_Tuhup', 'Puruk_Cahu', 'Taboneo_Anchorage', 'Tarusan', 'Teluk_Siwak', 'Ujung_Rumput']] = None
df2['week'] = sorted(set(df1.index.get_level_values('weekRaw').map(lambda x: x.split(' ')[0])))
df2.set_index('week', inplace=True)
df2['Muara_Teweh'] = df1.query("Location == 'Muara Teweh'").values
df2['Muara_Tuhup'] = df1.query("Location == 'Muara Tuhup'").values
df2['Puruk_Cahu'] = df1.query("Location == 'Puruk Cahu'").values
df2['Taboneo_Anchorage'] = df1.query("Location == 'Taboneo Anchorage'").values
df2['Tarusan'] = df1.query("Location == 'Tarusan'").values
df2['Teluk_Siwak'] = df1.query("Location == 'Teluk Siwak'").values
df2['Ujung_Rumput'] = df1.query("Location == 'Ujung Rumput'").values
yCol = [df2['Muara_Teweh'].to_numpy(),
df2['Muara_Tuhup'].to_numpy(),
df2['Puruk_Cahu'].to_numpy(),
df2['Taboneo_Anchorage'].to_numpy(),
df2['Tarusan'].to_numpy(),
df2['Teluk_Siwak'].to_numpy(),
df2['Ujung_Rumput'].to_numpy()]
pWeekly = figure(x_range=df2.index.to_list(), plot_height=300, plot_width=700,
title='Weekly test', tools='pan, wheel_zoom, box_zoom, reset', toolbar_location='right')
wP = pWeekly.vbar(x='x', top='y', source=ColumnDataSource({'x': df2.index.to_list(), 'y':yCol[0]}), width=0.5, color=Paired[7][0])
pWeekly.toolbar.autohide = True
pWeekly.grid.grid_line_dash = 'dotted'
pWeekly.grid.grid_line_dash_offset = 5
pWeekly.grid.grid_line_width = 2
pWeekly.outline_line_color=None
pWeekly.axis.major_label_text_font_style = 'bold'
pWeekly.axis.major_label_text_font_size = '11px'
pWeekly.axis.axis_label_text_font_style = 'bold'
pWeekly.xaxis.major_label_orientation = 45
pWeekly.yaxis[0].formatter = PrintfTickFormatter(format='%0.0f mm')
pWeekly.y_range.start = round(df2.min().min(), -3)
code = '''if (cb_data.source.selected.indices.length == 1){
var selected_index = cb_data.source.selected.indices[0];
week.data_source.data['y'] = yCol[selected_index]
week.data_source.change.emit();
}'''
tap = TapTool(renderers=[t2], behavior='select')
wP.select(tap).callback = CustomJS(args = {'week': wP, 'yCol': yCol}, code = code)
show(column([p1, pWeekly]))

How would you use JavaScript to create a toggle button that unhides/ hides content?

I am trying to hide content that is revealed when the button is clicked.
This is my starting HTML:
<div class="sunrise-section" id="hide-show">
<h3>SUNRISE</h3>
<p class="sunrise">5:40 A.M.</p>
</div>
<div class="sunset-section" id="hide-show">
<h3>SUNSET</h3>
<p class="sunset">8:05 P.M.</p>
</div>
<div class="navbar-bottom">
<button onclick="onClick"><img src="https://image.flaticon.com/icons/svg/892/892499.svg" alt="click for details" height="18px" id="navbar-bottom-button"></button>
</div>
This is my starting JavaScript (The onClick function is last; I included everything to show context):
window.addEventListener('load', ()=> {
let long;
let lat;
let locationTimeZone = document.querySelector('.location-timezone');
let temperatureDegree = document.querySelector('.temperature-degree');
let humidity = document.querySelector('.humidity');
let todayDate = document.querySelector('.today-date');
let windSpeed = document.querySelector('.wind-speed');
let visibility = document.querySelector('.visibility');
let pressure = document.querySelector('.pressure');
let sunrise = document.querySelector('.sunrise');
let sunset = document.querySelector('.sunset');
let myDate = new Date();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(position => {
long = position.coords.longitude;
lat = position.coords.latitude;
const proxy = 'https://cors-anywhere.herokuapp.com/';
const api = `${proxy}https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=d5f88bf8e740a9d82677f46f346f0a33&units=Imperial`;
fetch(api)
.then(response => {
return response.json();
})
.then(data => {
console.log(data);
// Set Sunrise
let sunriseDate = new Date(data.sys.sunrise * 1000);
let sunriseHours = sunriseDate.getHours();
let sunriseMinutes = sunriseDate.getMinutes();
// Set Sunset
let sunsetDate = new Date(data.sys.sunset * 1000);
let sunsetHours = sunsetDate.getHours();
let sunsetMinutes = sunsetDate.getMinutes();
// Add 0 Before Minutes if Less than 10
if(sunsetMinutes.toString().length < 2)
sunsetMinutes = "0" + sunsetMinutes
if(sunriseMinutes.toString().length < 2)
sunriseMinutes = "0" + sunsetMinutes
// Set DOM Elements from the API
locationTimeZone.textContent = data.name;
temperatureDegree.textContent = Math.round(data.main.temp);
humidity.textContent = data.main.humidity + '%';
todayDate.textContent = myDate.format('l F d') + 'th, ' + myDate.format('Y');
windSpeed.textContent = data.wind.speed + ' MPH';
visibility.textContent = Math.round(data.visibility / 1609) + '+ Mi';
pressure.textContent = data.main.pressure + ' mb';
sunrise.textContent = sunriseHours + ":" + sunriseMinutes + " A.M.";
sunset.textContent = (sunsetHours - 12) + ":" + sunsetMinutes + " P.M.";
// Set Icon
let iconCode = data.weather[0].icon;
let iconUrl = "http://openweathermap.org/img/wn/" + iconCode + "#2x.png";
$('#weather-icons').attr('src', iconUrl);
// Toggle Hide / Unhide Button
function onClick() {let x = document.getElementById("hide-show");
if (x.style.display === "none") {
x.style.display = "block";}
else {x.style.display = "none";}
}
} )
});
}
});
I've tried to change .getElementById("hide-show") to document.querySelectorAll('[id=hide-show]') and nothing changes.
I appreciate any input that can help me better understand this problem!
I think the onClick function is never called if you have your javascript in a separate file.
Here is a simple way to do this, it's called event delegation, it's better to have a single listener than multiple in a loop.
let elements = document.querySelectorAll('.hide-show');
document.addEventListener('click', e => {
if (e.target.closest('button')) {
elements.forEach(el => {
el.classList.contains('hidden') ? el.classList.remove('hidden') : el.classList.add('hidden');
})
}
})
.hidden {
display: none
}
<div class="sunrise-section hide-show" id="one">
<h3>SUNRISE</h3>
<p class="sunrise">5:40 A.M.</p>
</div>
<div class="sunset-section hide-show" id="two">
<h3>SUNSET</h3>
<p class="sunset">8:05 P.M.</p>
</div>
<div class="navbar-bottom">
<button><img src="https://image.flaticon.com/icons/svg/892/892499.svg" alt="click for details" height="18px" id="navbar-bottom-button"></button>
</div>

Categories

Resources