I am working on an alert-similar function in javascript, and I got in trouble.
The code of the first function (prepBkCrt) looks like this:
function prepBkCrt() {
event.preventDefault();
crtBkMnl = true;
crtBkCnl = false;
const url = crtBkTab.querySelector("#url");
const name = crtBkTab.querySelector("#name");
if (name.value.length >= 17) {
poper("Bookmark","I will pass this part",true).then((response) => {
if (response === false) {
crtBkCnl = true;
hideBkTab();
return;
}
});
}
addBookmark(url.value,name.value);
if (crtBkCnl === false) {
poper("Bookmark","Bookmark successfully created!",false);
}
url.value = "";
name.value = "";
}
and the second function looks like this:
function poper(headerTxt, descTxt, option) {
return new Promise((resolve, reject) => {
const poper = document.querySelector("#poper");
const header = poper.querySelector("h2");
const buttonDiv = poper.querySelector("div");
const desc = poper.querySelector("span");
header.innerText = headerTxt;
desc.innerHTML = descTxt;
const yBtn = buttonDiv.querySelectorAll("button")[0];
yBtn.addEventListener("click", (event) => {poper.style.transform = "translateY(-300px)"; resolve(true);});
const nBtn = buttonDiv.querySelectorAll("button")[1];
nBtn.addEventListener("click", (event) => {poper.style.transform = "translateY(-300px)"; resolve(false);});
if (option === false) {
nBtn.style.display = "none";
} else {
nBtn.style.display = "block";
}
poper.style.transform = "none";
setTimeout(() => {poper.style.transform = "translateY(-300px)"; resolve(false);},10000);
});
}
This used to work well on other code, but it seems to not work on this javascript file. I've checked that it does run the first poper function in prepBkCrt function, which is the problem. The expected behavior is if the name.value's length is over 17, it should run poper function (it should work like this, and run this one, but the code only runs the second image. What's the problem?
You seem to be looking for an else statement. The return inside the .then() callback does not break from prepBkCrt.
function prepBkCrt() {
event.preventDefault();
crtBkMnl = true;
crtBkCnl = false;
const url = crtBkTab.querySelector("#url");
const name = crtBkTab.querySelector("#name");
if (name.value.length >= 17) {
poper("Bookmark","I will pass this part",true).then(response => {
if (response === false) {
crtBkCnl = true;
hideBkTab();
}
});
} else {
addBookmark(url.value,name.value);
poper("Bookmark","Bookmark successfully created!",false);
url.value = "";
name.value = "";
}
}
Related
I use OOP system. I have one product list add project and ı want to capitalization check. I know two solution for problem but doesn't work.
For example, I entered a product called "bag" and again I want the same product not to be capitalized. Different letters such as "bag" and "Bag" or "BAG" should not be written in capital letters. how can ı fix this? Thanks advance for answer. (You just need to answer one of the two solutions.) Full code: https://codepen.io/BerkayAkgurgen/pen/bGBNojw
// Some Solution
function addProductToUI(e) {
const productName = nameInput.value.trim().toLowerCase();
const productModel = modelInput.value.trim();
const productPrice = priceInput.value.trim();
let products = getTodosFromStorage();
const urunlerim = new Urunler(productName, productModel, productPrice);
if (productModel == "" || productName == "" || productPrice == "") {
UI.showAlert("danger", "Hatalı Giriş")
} else if (todos.some(a => a.trim().toLowerCase() == newTodoValuee)) {
console.log("sdaas");
return false;
} else {
let control = false;
const products = Storage.getProductsFromStorage();
products.forEach(function (product) {
if (productName === product.productName) {
control = true;
}
});
if (control === false) {
UI.urunEkle(urunlerim);
Storage.addProductsToStorage(urunlerim);
UI.showAlert("success", "Başarılı Giriş");
nameInput.value = "";
modelInput.value = "";
priceInput.value = "";
} else {
UI.showAlert("danger", "Aynı Marka Girilemez");
}
}
e.preventDefault();
}
// Map Solution
function addProductToUI(e) {
const productName = nameInput.value.trim().toLowerCase();
const productModel = modelInput.value.trim();
const productPrice = priceInput.value.trim();
let products = getTodosFromStorage();
var words = todos.map(w => w.toLowerCase());
const urunlerim = new Urunler(productName, productModel, productPrice);
if (productModel == "" || productName == "" || productPrice == "") {
UI.showAlert("danger", "Hatalı Giriş")
} else if (words.includes(productName)) {
e.preventDefault();
console.log("Aynı Todo");
nameInput.value = "";
return false;
} else {
let control = false;
const products = Storage.getProductsFromStorage();
products.forEach(function (product) {
if (productName === product.productName) {
control = true;
}
});
if (control === false) {
UI.urunEkle(urunlerim);
Storage.addProductsToStorage(urunlerim);
UI.showAlert("success", "Başarılı Giriş");
nameInput.value = "";
modelInput.value = "";
priceInput.value = "";
} else {
UI.showAlert("danger", "Aynı Marka Girilemez");
}
}
e.preventDefault();
}
Ok, your code is huge, makes sense I guess, so I'll just give you a function you can use to only return common letters from a given text element(so that you can work with it)
The idea of how the function is used is that you store all values as lowercase FROM THE INPUT and do checks when INPUT IS ALREADY LOWERED
var x=document.getElementById('x')
function lowerCaseInput(elem){return elem.value.toLowerCase()}
var obj={}
document.getElementById('b')
.addEventListener('click',function(ev){
var input=lowerCaseInput(x)
if(obj[input]){alert(`Error: "${input}" already exists`)}
else{obj[input]=1; console.log(obj)}
})
<input id="x" />
<button id="b">add value</button>
I can't wrap my head around callback syntax, can you please help me re-write my code so that it executes in this order:
MenuBuilder.load()
MenuBuilder.draw()
Translator.load()
(in my case it executes in this order MenuBuilder.load(), Translator.load(), MenuBuilder.draw() so it doesn't do what I want)
onload.js
import MenuBuilder from "./menu-builder.js";
import Translator from "./translator.js";
var menuBuilder = new MenuBuilder();
var translator = new Translator();
menuBuilder.load();
translator.load();
menu-builder.js
"use strict"
class MenuBuilder {
constructor() {
this._nav = document.getElementsByTagName("nav")[0];
this._url = window.location.href;
}
load() {
console.log("MenuBuilder.load() start");
fetch(`/json/menu.json`)
.then((res) => res.json())
.then((jsonMenu) => {
this.draw(jsonMenu);
})
/*.catch(() => {
console.error(`Could not load ${this._lang}.json.`);
});*/
console.log("MenuBuilder.load() end");
}
draw(jsonMenu) {
console.log("MenuBuilder.draw(jsonMenu) start");
var htmlMenu = `<div id="siteTitleDiv"><p id="siteTitle" data-i18n="general.title"></p><p id="siteTitleShadow" data-i18n="general.title-shadow"></p><p id="siteSubtitle"data-i18n="general.subtitle"></p></div><ul>`;
for(var i = 0; i < jsonMenu.length; i++) {
var menuItem = jsonMenu[i];
var regexp = /http:\/\/cypher-f\.com\/(([a-z\-]*\/)?([a-z\-]*\/))?/g;
var fullPage = "something format_abc";
var match = regexp.exec(this._url);
var level_1 = match[1];
var level_2 = match[3];
var parent = match[2];
var full_suffix = match[0];
if ((parent == null) || (menuItem.parent === parent)) {
var material_icon = menuItem["material-icon"];
var href = menuItem["href"];
var i18n = menuItem["data-i18n"];
htmlMenu += `<li><i class="material-icons">${material_icon}</i></li>`;
}
}
htmlMenu += `</ul>`;
this._nav.innerHTML = htmlMenu;
console.log("MenuBuilder: nav.innerHTML");
console.log(this._nav.innerHTML);
console.log("MenuBuilder: document.elements");
console.log(document.querySelectorAll("[data-i18n]"));
console.log("MenuBuilder.draw(jsonMenu) end");
}
}
export default MenuBuilder;
translator.js
"use strict"
class Translator {
constructor() {
this._lang = this.getLanguage();
this._elements = document.querySelectorAll("[data-i18n]");
}
getLanguage() {
var lang = navigator.languages ? navigator.languages[0] : navigator.language;
return lang.substr(0, 2);
}
load(lang = null) {
console.log("Translator.load() start");
console.log("this._elements");
console.log(this._elements);
if (lang) {
this._lang = lang;
}
else {
var re = new RegExp("lang=([^;]+)");
var value = re.exec(document.cookie);
var cookieLang = (value != null) ? unescape(value[1]) : null;
if (cookieLang) {
this._lang = cookieLang;
}
}
fetch(`/i18n/${this._lang}.json`)
.then((res) => res.json())
.then((translation) => {
this.translate(translation);
})
.then(this.toggleLangTag())
.then(document.cookie = `lang=${this._lang};path=/`)
/*.catch(() => {
console.error(`Could not load ${this._lang}.json.`);
});*/
console.log("Translator.load() end");
}
translate(translation) {
console.log("Translator.load(translation) start");
this._elements.forEach((element) => {
var keys = element.dataset.i18n.split(".");
var text = keys.reduce((obj, i) => obj[i], translation);
if (text) {
element.innerHTML = text;
}
else {
element.innerHTML = `key ${keys} not found for ${this._lang}!`
}
});
console.log("Translator.load(translation) end");
}
toggleLangTag() {
if (document.documentElement.lang !== this._lang) {
document.documentElement.lang = this._lang;
}
}
switchLanguage(translator) {
var availableLang = ["en", "fr"];
var currentLangIndex = availableLang.indexOf(translator._lang);
var nextLang = availableLang[(currentLangIndex + 1)%availableLang.length];
translator.load(nextLang);
}
}
export default Translator;
I'm sorry I know this is kind of a newbie question but I haven't programmed in three years.
You're working with Promises here, so you want to stick with that paradigm. Return the promise that is returned from the fetch call, then "chain" off of that promise to call the translator.
load() {
console.log("MenuBuilder.load() start");
// The return here gives control of the promise to the caller...
return fetch(`/json/menu.json`)
.then((res) => res.json())
.then((jsonMenu) => {
this.draw(jsonMenu);
})
/*.catch(() => {
console.error(`Could not load ${this._lang}.json.`);
});*/
console.log("MenuBuilder.load() end");
}
So back in onload.js you can use the promise returned from menuBuilder.load() to call translator.load() after menuBuilder.load() is done.
import MenuBuilder from "./menu-builder.js";
import Translator from "./translator.js";
var menuBuilder = new MenuBuilder();
var translator = new Translator();
menuBuilder.load().then(() => translator.load());
I am trying to assign the value of boxSpaces[0] to the variable result in the function decalreWinner() but the assignment is not taking place.
function assignSpace(mark, box) {
const image = document.createElement("img");
const src = mark === "x" ? X_IMAGE_URL : O_IMAGE_URL;
image.src = src;
box.appendChild(image);
box.removeEventListener("click", changeToX);
const id = parseInt(box.dataset.id);
boxSpaces[id] = mark;
}
function isGameOver() {
const length = emptyBoxes.length;
if (length <= 0) {
declareWinner();
return true;
} else {
false;
}
}
function declareWinner() {
const result = "";
if (boxSpaces["0"] === boxSpaces["1"] && boxSpaces["1"] === boxSpaces["2"]) {
result = boxSpaces["0"];
console.log(result);
}
return result;
}
You are using const to declare a variable and you are tring to update it which is not possible. change it to let or var
function declareWinner() {
let result = ""; //change it to let or var
if (boxSpaces["0"] === boxSpaces["1"] && boxSpaces["1"] === boxSpaces["2"]) {
result = boxSpaces["0"];
console.log(result);
}
return result;
}
I wrote a function that trigger on input and get data from API. I need to store last input.value in localStorage and then set input.value to one in localStorage on reload. Everything is fine except when I reload the page I have value that I need but I have to click space then backspace f.e. to render things. I would like to ask where should I pass the getter from localStorage so it will trigger the function on reload, but won't break the listener for input. There is full code underneath :
let country;
let cities = [];
const citiesDiv = document.getElementById("cities");
const countryPicker = document.getElementById("country-picker");
const getData = async () => {
const response = await fetch(
`https://api.openaq.org/v1/cities?country=${country}&limit=10¶meter=no2&order_by=parameter`
);
const data = await response.json();
cities = data.results;
console.log(cities);
citiesDiv.innerHTML = "";
renderCities(cities);
};
countryPicker.value = JSON.parse(localStorage.getItem("inputValue"));
countryPicker.addEventListener("input", function(e) {
if (e.target.value.toLowerCase() === "poland".toLowerCase()) {
country = "PL";
} else if (e.target.value.toLowerCase() === "spain".toLowerCase()) {
country = "ES";
} else if (e.target.value.toLowerCase() === "germany".toLowerCase()) {
country = "DE";
} else if (e.target.value.toLowerCase() === "france".toLowerCase()) {
country = "FR";
}
localStorage.setItem("inputValue", JSON.stringify(e.target.value));
getData();
});
function renderCities(cities) {
cities.forEach(function(city) {
const p = document.createElement("p");
const button = document.createElement("button");
button.classList.add("accordion");
const div = document.createElement("div");
div.classList.add("panel");
const citiesDiv = document.getElementById("cities");
button.textContent = city.city;
citiesDiv.appendChild(button);
citiesDiv.appendChild(div);
div.appendChild(p);
p.textContent = "Lorem ipsum";
});
const acc = document.getElementsByClassName("accordion");
let i;
for (i = 0; i < acc.length; i++) {
console.log(i);
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
}
Refactor your code in order to make the function that fetches and renders data to be reusable for two cases:
when user changes the input.
when the page is loaded.
Replace the following part
countryPicker.value = JSON.parse(localStorage.getItem("inputValue"));
countryPicker.addEventListener("input", function(e) {
if (e.target.value.toLowerCase() === "poland".toLowerCase()) {
country = "PL";
} else if (e.target.value.toLowerCase() === "spain".toLowerCase()) {
country = "ES";
} else if (e.target.value.toLowerCase() === "germany".toLowerCase()) {
country = "DE";
} else if (e.target.value.toLowerCase() === "france".toLowerCase()) {
country = "FR";
}
localStorage.setItem("inputValue", JSON.stringify(e.target.value));
getData();
});
with
countryPicker.value = JSON.parse(localStorage.getItem("inputValue"));
fetchAndRender(countryPicker.value);
countryPicker.addEventListener("input", e => fetchAndRender(e.target.value));
function fetchAndRender(value) {
if (value.toLowerCase() === "poland".toLowerCase()) {
country = "PL";
} else if (value.toLowerCase() === "spain".toLowerCase()) {
country = "ES";
} else if (value.toLowerCase() === "germany".toLowerCase()) {
country = "DE";
} else if (value.toLowerCase() === "france".toLowerCase()) {
country = "FR";
}
localStorage.setItem("inputValue", JSON.stringify(value));
getData();
}
I am new to javascript. I would like someone to explain to me why this form keeps getting submitted even if it fails the validation? I am not allowed to use any validation plugins hence I wrote several functions for validation.
/* EMAIL VALIDATION */
let validateEmailInput = (anEmail) => {
let emailRegex = /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
if (anEmail.value.search(emailRegex) !== -1 || anEmail.value.match(emailRegex)) {
document.getElementById("errorOutput1").innerText = "";
return true;
} else {
document.getElementById("errorOutput1").innerText = "Invalid email!";
anEmail.focus();
return false;
}
}
/* RADIO VALIDATION */
let validateRadioInput = (name) => {
let radios = document.getElementsByName("part1_radio");
let isCheckedRadio = false;
let numRadioChecked = 0;
let radioChosen;
for (let i = 0; i < radios.length && !isCheckedRadio; i++) {
if (radios[i].checked) {
numRadioChecked++;
document.getElementById("errorOutput2").innerText = "";
radioChosen = radios.item(i).id;
isCheckedRadio = true;
}
} //end for
if (numRadioChecked === 0) {
document.getElementById("errorOutput2").innerText = "Please select one season!";
isCheckedRadio = false;
}
return isCheckedRadio;
}
/* CHECKBOX VALIDATION */
let validateCheckboxInput = (name) => {
let checkboxGroup = document.getElementsByName("part1_checkbox");
let isCheckedCheckbox = false;
let numCheckboxChecked = 0;
let checkboxChosen;
for (let i = 0; i < checkboxGroup.length && !isCheckedCheckbox; i++) {
if (checkboxGroup[i].checked) {
numCheckboxChecked++;
document.getElementById("errorOutput3").innerText = "";
checkboxChosen = checkboxGroup[i];
isCheckedCheckbox = true;
} else {
// if (numCheckboxChecked === 0) {
document.getElementById("errorOutput3").innerText = "Please check at least one country!";
isCheckedCheckbox = false;
}
} // end for
return isCheckedCheckbox;
}
/* SELECT/OPTIONS VALIDATION */
let validateSelectInput = (aSelection) => {
let selectGroup = document.getElementsByName("part1_select");
let isCheckedSelect = false;
let numCheckedSelect = 0;
let selectedVar;
if (!selectGroup.value) {
document.getElementById("errorOutput4").innerText = "Please choose one!";
isCheckedSelect = false;
} else {
isCheckedSelect = true;
selectedVar = selectGroup.value;
}
return isCheckedSelect;
}
This function is called inline like this:
<form id="myForm_part1" name="myForm_part1"action="someemailhere" method="post" onsubmit="validateForm(this.form);" novalidate>
I need help understanding why this happens.
function validateForm(form) {
let email = document.getElementById("part1_email");
let radioChoice = document.getElementsByName("part1_radio");
let checkboxChoice = document.getElementsByName("part1_checkbox");
let selectChoice = document.getElementById("part1_select");
$('#myForm_part1').submit(function() {
if (!validateEmailInput(email) || !validateRadioInput(radioChoice)
|| !validateCheckboxInput(checkboxChoice) || !validateSelectInput(selectChoice)) {
return false;
}
});
}
There is an issue with the onsubmit handler. Try changing
onsubmit="validateForm(this.form);"
to
onsubmit = "return validateForm(this.form);"
Without the return statement the submit handler, which is a function compiled from the attribute value, returns undefined because it doesn't have a return statement.
Use preventDefault() to stop submission if validation fails.
function validateForm(form) {
let email = document.getElementById("part1_email");
let radioChoice = document.getElementsByName("part1_radio");
let checkboxChoice = document.getElementsByName("part1_checkbox");
let selectChoice = document.getElementById("part1_select");
$('#myForm_part1').submit(function(event) {
if (!validateEmailInput(email) || !validateRadioInput(radioChoice)
|| !validateCheckboxInput(checkboxChoice) || !validateSelectInput(selectChoice)) {
event.preventDefault();
}
});
}