cannot change language of text based on localStorage at button click - javascript

I made buttons to switch language of data on click based on localStorage language item value, but it does not work as expected
HTML:
<a id="arbutton" href="#ar">arabic</a>
<a id="enbutton" href="#en">english</a>
<a id="" href="localStorage1.html">page</a>
<!-- data here will change -->
<div id="hello">yes language</div>
JS:
var creatbtnAr = document.querySelector('#arbutton');
var creatbtnEn = document.querySelector('#enbutton');
// button language arabic
creatbtnAr.addEventListener('click', event => {
localStorage.setItem("language", "ar");
console.log(localStorage.language);
});
// button language english
creatbtnEn.addEventListener('click', event => {
localStorage.setItem("language", "en");
console.log(localStorage.language);
});
// methods
var lg = localStorage.getItem.language;
function translate(lg) {
if(lg == 'ar') {
document.querySelector('#hello').textContent = 'u arabic';
}
if(lg == 'en') {
document.querySelector('#hello').textContent = 'u english';
}
}
https://codepen.io/pen/?editors=1111

Try this:
var creatbtnAr = document.querySelector('#arbutton');
var creatbtnEn = document.querySelector('#enbutton');
// button language arabic
creatbtnAr.addEventListener('click', event => {
localStorage.setItem("language", "ar");
console.log(localStorage.language);
translate();
});
// button language english
creatbtnEn.addEventListener('click', event => {
localStorage.setItem("language", "en");
console.log(localStorage.language);
translate();
});
// methods
function translate() {
const lg = localStorage.getItem("language");
if(lg == 'ar') {
document.querySelector('#hello').textContent = 'u arabic';
}
if(lg == 'en') {
document.querySelector('#hello').textContent = 'u english';
}
}

Related

How can I get action events to work with template strings

Problem
Rendered HTML template literal action events won't work
Stack MEVN with handlebars
code
renderData.js
const template = function (data) {
return `<div class="vvn_siteContent sc_flex">
<span class="sc_flex">
<img src="https://images.wallpaperscraft.com/image/single/keyboard_backlight_light_159518_1280x720.jpg" alt="" class="sc_img">
<div class="sc_flex sc_column">
<label class="sc_label">${data.category} :: ${data.titles.main}</label>
<div class="sc_desc" style="word-wrap: break-word">
${data.desc.main}
</div>
<div class="vvn_editTypes">
<button class="sc_button sc_resetBTN">Delete</button>
<button class="sc_button sc_scheduleBTN" >Hide</button>
<button class="sc_button sc_sendBTN" dataset-data="${data._id}" onclick="myData()" >Edit!</button>
</div>
</div>
</span>
</div>`
}
export const renderData = function (key) {
const keyToLowerCase = key.toLowerCase();
const getKeyData = handleJSON(keyToLowerCase);
getContainer.innerHTML = " ";
const parser = new DOMParser();
for (let i = 0; i < getKeyData[0][0].pageContent.length; i++) {
const { ...data } = getKeyData[0][0].pageContent[i];
const html = template(data);
const parsedDoc = parser.parseFromString(html, "text/html");
getContainer.append(...parsedDoc.body.children);
}
}
oneCRUD.js //this is the file that is loaded via
<script type="module" src="../js/OneCRUD.js" type="text/javascript" data="{{data2}}"></script>
this script tag is at the bottom of the index.html
const allBtns = document.querySelectorAll('.vvn_editTypes').forEach(el => el.addEventListener('click', (e) => {
console.log(e.target)
console.log(e)
if(e.target.textContent === 'Delete') console.log('Deleting')
if(e.target.textContent === 'Hide') console.log('Hiding')
if(e.target.textContent === 'Edit!') console.log('Editing')
}))
function myData () {
console.log('this wont get called even if i gave the button onclick="myData()")
}
If I try to call a function in onclick I will get error function name undefined
My problem is pretty straight forward. I am trying to attach events to the buttons in renderData.js from file oneCRUD.js and its not working.
Appreciate the help
I found a solution
code
const allBtns = document.querySelectorAll('.vvn_siteContent').forEach(el => el.addEventListener('click', (e) => {
console.log(e.target)
console.log(e)
if(e.target.textContent === 'Delete') console.log('Deleting')
if(e.target.textContent === 'Hide') console.log('Hiding')
if(e.target.textContent === 'Edit!') console.log('Editing')
}))
notice how the element I'm selecting is inside the template literal
I need to select the parent of that element.
so now my code looks like this:
const allBtns = document.querySelectorAll('.vvn_siteContentList').forEach(el => el.addEventListener('click', (e) => {
console.log(e.target)
console.log(e)
if(e.target.textContent === 'Delete') console.log('Deleting')
if(e.target.textContent === 'Hide') console.log('Hiding')
if(e.target.textContent === 'Edit!') console.log('Editing')
}))
now the allBtns function works.
why does this work?
thats a good question

How to Disable this save/submit button?

I am wondering what is the best method to disable this save button after one click?
Here is the code :
<button data-bind="enable: !$root.isSaving(), click: $root.addNewCard.bind($data, $root)" class="primary button" role="button" data-size="sm">
Save
</button>
Above is the .cshtml code
Below is the javascript code:
BillingInformation.prototype.addNewCard = function (parent, creditCard) {
parent.isSaving(true);
parent.isSettingDefault(true);
creditCard.cardNumber(creditCard.cardNumber().replace(/-|\s/g, ''));
let $form = $('#addNewCardForm' + creditCard.walletItemId()),
cardNumber = creditCard.cardNumber();
parseDynamicFormElements($form);
if ($form.valid()) {
verifyAddress($form, function () {
authentication.checkReAuthenticatedThenLaunchLoginOrExecuteTask(() => {
creditCard
.save()
.then(response => {
if (response.status === HTTP_STATUS_OK) {
creditCard.walletItemId(response.content);
parent.walletItems.push(creditCard);
creditCard.lastFourDigits(
creditCard.cardNumber() ? creditCard.cardNumber().substr(-4) : ''
);
creditCard.obfuscatedCardNumber(cardNumber.replace(/.(?=.{4})/g, '*'));
parent.newCardInstance(new CreditCard({paymentType: 'creditCards'}));
checkForRedirect();
} else {
let container = document.createElement('div');
container.append(
'We were unable to save your payment information. Please try again or give us a call at 1-800-461-8898'
);
smartPak.ui.modal(container, {
title: 'Unable to Save Payment Method',
buttons: {
Close: function (modal) {
modal.close();
}
}
});
}
})
.then(() => {
parent.isSaving(false);
});
});
});
parent.isSaving(false);
} else {
parent.isSaving(false);
parent.isSettingDefault(false);
}
};
What is the best method to prevent this from being clicked more than once after submission? currently if clicked multiple times it will duplicate the cc.
Thank you!
Maybe the the enable property should bind to a variable, not a function like you do in
enable: !$root.isSaving()
did you try switching click:
$root.addNewCard.bind($data, $root) to click: $root.addNewCard.bind($root, $data) ?
according to your declaration:
BillingInformation.prototype.addNewCard = function (parent, creditCard)
creditCard = $data from the form and parent = $root ?

how to return created attribute in javascript

I'm having trouble retrieving data from a data-tag attribute on a button that is created by createElement
chatbot.js
const selectServiciosMoviles = document.querySelector('#selectServiciosMoviles')
const addSelect = (select, id, datatag) => {
const selection = document.createElement('button')
selection.classList.add('chatbot__selection')
selection.id = id
selection.setAttribute("data-tag", datatag)
selection.innerHTML = select
messageArea.appendChild(selection)
scrollToBottom(messageArea)
}
selectServiciosMoviles.addEventListener('click', () => {
setTimeout(() => {
addSelect('Portabilidad', 'selectPortabilidad', '{"categoria":"chatbot", "nombre":"chatbot","ubicacion":"home_b2b", "accion":"seleccionar", "etiqueta":"subcategoria_portabilidad"}')
addSelect('Planes Moviles', 'selectMoviles', '{"categoria":"chatbot", "nombre":"chatbot","ubicacion":"home_b2b", "accion":"seleccionar", "etiqueta":"subcategoria_planes_moviles"}')
addSelect('Roaming', 'selectRoaming', '{"categoria":"chatbot", "nombre":"chatbot","ubicacion":"home_b2b", "accion":"seleccionar", "etiqueta":"subcategoria_roaming"}')
addSelect('Seguro Movil', 'selectSeguros', '{"categoria":"chatbot", "nombre":"chatbot","ubicacion":"home_b2b", "accion":"seleccionar", "etiqueta":"subcategoria_seguro_movil"}')
scrollToBottom()
}, 2000)
});
html
<button class="chatbot__selection" id="selectPortabilidad" data-tag="{"categoria":"chatbot", "nombre","chatbot", "ubicacion":"home_b2b", "accion":"seleccionar","etiqueta":"subcategoria_portabilidad"}">Portabilidad</button>
<button class="chatbot__selection" id="selectMoviles" data-tag="{"categoria":"chatbot", "nombre","chatbot", "ubicacion":"home_b2b", "accion":"seleccionar","etiqueta":"subcategoria_portabilidad"}">Planes Moviles</button>
<button class="chatbot__selection" id="selectRoaming" data-tag="{"categoria":"chatbot", "nombre","chatbot", "ubicacion":"home_b2b", "accion":"seleccionar","etiqueta":"subcategoria_portabilidad"}">Roaming</button>
<button class="chatbot__selection" id="selectSeguros" data-tag="{"categoria":"chatbot", "nombre","chatbot", "ubicacion":"home_b2b", "accion":"seleccionar","etiqueta":"subcategoria_portabilidad"}">Seguro Movil</button>
libreria.js
var tagItems = document.querySelectorAll('[data-tag]')
tagItems.forEach(function (e) {
e.addEventListener('click', function (e) {
if(e.target.dataset.tag != undefined){
var data = JSON.parse(e.target.dataset.tag)
console.log(data)
}
})
})
the problem when seeing the console nothing appears to me, the data-tag of the button does not rescue me. please i need help, thanks

JQuery cloned element

I am stuck on this problem. I am coding a task platform app. Whenever I try to save, the task clones itself. After each "Save Changes," there are more and more clones. I have rewritten the code so many times. But still, I am not successful. Please help me to find the error.
$("#taskSave").click(() => {
const task = {
id: Date.now(),
imageUrl: $("#imageInput").val(),
title: $("#titleInput").val(),
description: $("#descriptionInput").val(),
type: $("#typeInput").val(),
};
$("#overlay").hide();
todos.push(task);
saveStorage(todos);
// reset input values
$("#imageInput").val("");
$("#titleInput").val("");
$("#descriptionInput").val("");
$("#typeInput").val("");
});
function saveStorage(todos) {
localStorage.setItem("todos", JSON.stringify(todos));
display(todos);
};
function display(todos) {
$("#taskBoard").innerHTML = "";
// .html("");
todos.forEach(item => {
let c = document.createElement("div");
c.setAttribute("class", "card");
c.setAttribute('id', item.id);
c.innerHTML = `
<div class="cardTop">
<div class="binContainer">
<div class="binImage"></div>
</div>
</div>
<img src="${item.imageUrl}" alt="task image">
<h2>${item.title}<h2>
<p>${item.description}</p>
<div class="cardType">${item.type}</div>
`;
$("#taskBoard").append(c);
// end
});
};
I've created a minimal working example, and the problem is in the cleanup of the HTML. You cannot use innerHTML on the JQuery object, or you use its html function or you need to retrieve the javascript object with $("#taskBoard")[0].
// You can use:
$("#taskBoard").html("");
// or
// document.getElementById("taskBoard").innerHTML = "";
// or
// $("#taskBoard")[0].innerHTML = "";
// But not:
// $("#taskBoard").innerHTML = "";
The working example here on JSFiddle (on SO dont work localStorage)
let todos = [];
$("#taskSave").click(() => {
const task = {
id: Date.now()
};
todos.push(task);
saveStorage(todos);
});
function saveStorage(todos) {
localStorage.setItem("todos", JSON.stringify(todos));
display(todos);
console.log(todos);
};
function display(todos) {
$("#taskBoard").html("");
// or
// document.getElementById("taskBoard").innerHTML = "";
// or
// $("#taskBoard")[0].innerHTML = "";
// But not
// $("#taskBoard").innerHTML = "";
todos.forEach(item => {
let c = document.createElement("div");
c.innerHTML = `
<p>${item.id}</p>
`;
$("#taskBoard").append(c);
});
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="taskSave">
SAVE
</button>
<div id="taskBoard">
</div>

Why am I getting a TypeError not a function. Calling forEach on an array object

For a bit of background information: this app is supposed to load a map api and create a workout form linked to a location selected on the map by clicking. Once the map is clicked, a form is loaded to fill out info about that workout and then it's saved to the #workout variable.
Problem: I'm trying to save the #workout variable to local storage to then load all the workouts from storage whenever the page is reloaded.
I'm trying to run the _getLocalStorage() function in the constructor to load items from the local storage when the page loads, but I keep getting this TypeError code:
script.js:239 Uncaught TypeError: this[#workout].forEach is not a function
at App._getLocalStorage (script.js:239)
at new App (script.js:21)
Code:
class App {
#map;
#mapEvent;
#workout = [];
constructor() {
this._getPosition();
this._getLocalStorage();
form.addEventListener('submit', this._newWorkout.bind(this));
inputType.addEventListener('change', this._toggleElevationField);
containerWorkouts.addEventListener('click', this._panToWorkout.bind(this));
}
_panToWorkout(e) {
// find the workout
const workoutEl = e.target.closest('.workout');
if (!workoutEl) return;
const workout = this.#workout.find(
work => work.id === workoutEl.dataset.id
);
// pan to workout object with that id number
this.#map.setView(workout.coords, 13, {
animate: true,
pan: {
duration: 1,
easeLinearity: 0.8,
},
});
}
_getPosition() {
// -> check if this nagivator.geolocation object exits, then loads the map.
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
this._loadMap.bind(this),
function () {
alert("Can't get your position");
}
);
}
}
_loadMap(position) {
const { latitude, longitude } = position.coords;
// -> creating a coordinate variable because the below L.map().setView function expects an array for the coordinates.
// -> adding the map loading script from the imported library after getting coordinates
this.#map = L.map('map').setView([latitude, longitude], 13);
L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png').addTo(
this.#map
);
// -> SETUP MAP CLICK LISTENER && OPEN FORM
this.#map.on('click', this._showForm.bind(this));
}
_showForm(event) {
this.#mapEvent = event;
form.classList.remove('hidden');
inputDistance.focus();
}
_hideForm() {
// -> Clear form values when submit
inputDistance.value =
inputCadence.value =
inputDuration.value =
inputElevation.value =
'';
// -> removes the form from view to disable the slide transition while it's being removed.
form.style.display = 'none';
form.classList.add('hidden');
setTimeout(() => (form.style.display = 'grid'), 1000);
}
_toggleElevationField() {
inputElevation.closest('.form__row').classList.toggle('form__row--hidden');
inputCadence.closest('.form__row').classList.toggle('form__row--hidden');
}
_newWorkout(e) {
// -> prevent default submit function which is to refresh the page
e.preventDefault();
const validInput = (...inputs) =>
inputs.every(entry => Number.isFinite(entry));
const allPositive = (...inputs) => inputs.every(inp => inp > 0);
// -> Get data from form
const type = inputType.value;
const distance = +inputDistance.value;
const duration = +inputDuration.value;
const { lat, lng } = this.#mapEvent.latlng;
let workout;
// -> if running, create running object
if (type === 'running') {
// -> check if data is valid
const cadence = +inputCadence.value;
if (
!validInput(distance, duration, cadence) ||
!allPositive(distance, duration, cadence)
) {
return alert('Inputs have to be a positive number.');
}
workout = new Running([lat, lng], distance, duration, cadence);
}
// -> if cycling, create cycling object
if (type === 'cycling') {
const elevation = +inputElevation.value;
// -> check if data is valid
if (
!validInput(distance, duration, elevation) ||
!allPositive(distance, duration)
)
return alert('Inputs have to be a positive number.');
workout = new Cycling([lat, lng], distance, duration, elevation);
}
// -> adds workout to workout array
this.#workout.push(workout);
// -> render the workout
this._renderWorkoutMarker(workout);
// -> Render workout on list
this._renderWorkout(workout);
// -> hide the form
this._hideForm();
// -> save workouts to storage
this._setLocalStorage();
}
_renderWorkoutMarker(workout) {
// -> DISPLAY MAP MARKER ON SUBMIT
L.marker(workout.coords)
.addTo(this.#map)
.bindPopup(
L.popup({
minWidth: 250,
maxWidth: 100,
autoClose: false,
closeOnClick: false,
className: `${workout.type}-popup`,
})
)
.setPopupContent(
`${workout.type === 'cycling' ? 'πŸš΄β€β™‚οΈ' : 'πŸƒβ€β™‚οΈ'} ${workout.description}`
)
.openPopup();
}
_renderWorkout(workout) {
let html = `
<li class="workout workout--${workout.type}" data-id="${workout.id}">
<h2 class="workout__title">${workout.description}</h2>
<div class="workout__details">
<span class="workout__icon">${
workout.type === 'cycling' ? 'πŸš΄β€β™‚οΈ' : 'πŸƒβ€β™‚οΈ'
}</span>
<span class="workout__value">${workout.distance}</span>
<span class="workout__unit">km</span>
</div>
<div class="workout__details">
<span class="workout__icon">⏱</span>
<span class="workout__value">${workout.duration}</span>
<span class="workout__unit">min</span>
</div>
`;
if (workout.type === 'running') {
html += `
<div class="workout__details">
<span class="workout__icon">⚑️</span>
<span class="workout__value">${workout.pace.toFixed(1)}</span>
<span class="workout__unit">min/km</span>
</div>
<div class="workout__details">
<span class="workout__icon">🦢🏼</span>
<span class="workout__value">${workout.cadence.toFixed(1)}</span>
<span class="workout__unit">spm</span>
</div>
</li>
`;
}
if (workout.type === 'cycling') {
html += `
<div class="workout__details">
<span class="workout__icon">⚑️</span>
<span class="workout__value">${workout.speed.toFixed(1)}</span>
<span class="workout__unit">km/h</span>
</div>
<div class="workout__details">
<span class="workout__icon">β›°</span>
<span class="workout__value">${workout.elevation.toFixed(1)}</span>
<span class="workout__unit">m</span>
</div>
</li>
`;
}
form.insertAdjacentHTML('afterend', html);
}
_setLocalStorage() {
localStorage.setItem('workouts', JSON.stringify(this.#workout));
}
_getLocalStorage() {
const data = JSON.parse(localStorage.getItem('workouts'));
if (!data) return;
this.#workout = data;
console.log(typeof this.#workout);
this.#workout.forEach(work => {
this._renderWorkout(work);
});
}
}
It seems like the result of const data = JSON.parse(localStorage.getItem('workouts')); is not Array.
So you can check it as below
console.log(JSON.parse(localStorage.getItem('workouts')));

Categories