How to change link (href) when i change language (option) ? | JavaScript - javascript

Please, Help me. I know how to translate text from json, but i don't understand how to change "href". How can i change "href" in the link by my switcher? I need to change links to right lang... link 1 for EN. link 2 for GER
My lang switcher
select.locale-switcher(data-lang-switcher='')
option(value='en') EN
option(value='ger') GER
my link
.contacts__item
a.agreement(data-lang="license" href="www.link1.com" LICENSE AGREEMENT
my js
const defaultLocale = "en";
let locale;
let translations = {};
document.addEventListener("DOMContentLoaded", () => {
setLocale(defaultLocale);
bindLocaleSwitcher(defaultLocale);
changeLink()
});
async function setLocale(newLocale) {
if (newLocale === locale) return;
const newTranslations =
await fetchTranslationsFor(newLocale);
locale = newLocale;
translations = newTranslations;
translatePage();
}
async function fetchTranslationsFor(newLocale) {
const response = await fetch(`/lang/${newLocale}.json`);
return await response.json();
}
function translatePage() {
document
.querySelectorAll("[data-lang]")
.forEach(translateElement);
}
function translateElement(element) {
const key = element.getAttribute("data-lang");
const translation = translations[key];
element.innerText = translation;
}
function bindLocaleSwitcher(initialValue) {
const switcher = document.querySelector("[data-lang-switcher]");
switcher.value = initialValue;
switcher.onchange = (e) => {
// Set the locale to the selected option[value]
setLocale(e.target.value);
};
}
I tried by json, by setAttribute, but nothing

Related

How to add more language in my Highlight.js

Based on the code sample, how to add new language like c#, php, java, sql, etc. This sample was provided by a man who answered my question last month. I tried to add new languages but not working. Thanks.
const container = document.querySelector('.container');
const removeTextNodes = el =>
[...el.childNodes].forEach(child => child.nodeType !== 1 && el.removeChild(child))
const format = (text, language) => {
switch (language) {
case 'html': return html_beautify(text);
case 'css': return css_beautify(text);
case 'js': return js_beautify(text);
default: return text;
}
}
const preProcess = code => {
removeTextNodes(code.closest('pre'));
const language = [...code.classList].find(cls => /language-/.test(cls));
const [ match, lang ] = language?.match(/language-(\w+)/);
const content = code.innerHTML.trim();
code.innerHTML = format(lang === 'html' ? _.escape(content) : content, lang);
};
const insertCode = (e) => {
e.preventDefault();
const content = e.target.elements.content.value.trim();
const language = e.target.elements.language.value;
if (content) {
const formatted = format(content, language);
const pre = document.createElement('pre');
const code = document.createElement('code');
code.classList.add(`language-${language}`, 'hljs');
code.innerHTML = hljs.highlight(formatted, { language }).value;
pre.append(code);
container.prepend(pre);
}
}
document.forms['add'].addEventListener('submit', insertCode);
document.querySelectorAll('code[class^="language-"]').forEach(preProcess);
hljs.highlightAll();
You can check the loaded languages with
hljs.listLanguages()
If this list doesn't contain the language, you want to use, you can load your language script-wise.
For example i wanted to use latex, so i added this script:
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/latex.min.js"></script>

Best way to make file buffer accessible outside a callback function in Javascript for large files?

I am new to JS, and I need to load a file1, decompress a part of it to file2, and then make that decompressed file2 available to user's download--all completely browser-side (no Node.js etc.).
For decompression I have:
let fb;
const decB = document.querySelector('button[id="dec"]')
const inputB = document.querySelector('input[type="file"]')
input.addEventListener('change', function(e) {
const r = new FileReader()
r.onload = function () {
const archive = new Uint8Array(r.result, start, length)
try {
fb = pako.inflate(archive);
} catch (err) {
console.log(err);
}
}
r.readAsArrayBuffer(input.files[0])
}, false)
decB.addEventListener("click", function(e) {
try {
const t = new TextDecoder().decode(fb)
console.log(t)
} catch(err) {
console.log(err)
}
}, false)
I want to be able to access the contents of the result in other functions. Is using a global variable the best way to do it, or is there a more proper solution?
Here is a tiny dependency free variant
function decompressBlob(blob) {
const ds = new DecompressionStream('gzip');
const decompressedStream = blob.stream().pipeThrough(ds);
return new Response(decompressedStream).blob();
}
function compressBlob(blob) {
const ds = new CompressionStream('gzip');
const decompressedStream = blob.stream().pipeThrough(ds);
return new Response(decompressedStream).blob();
}
const file = new File(['abc'.repeat(100)], 'filename.txt')
console.log('original file size', file.size)
compressBlob(file).then(async newBlob => {
console.log('compressed blob size:', newBlob.size)
const decompressedBlob = await decompressBlob(newBlob)
const content1 = await decompressedBlob.text()
const content2 = await file.text()
const expected = 'abc'.repeat(100)
console.log('same content:', content1 === expected)
console.log('same content:', content2 === expected)
})
Then if you want to download it create a object url and attach it to a link with a download attribute
a = document.createElement('a')
a.href = Object.createObjectURL(blob)
a.download = originalFile.name + '.gz'
a.click()
I guess if you want to avoid callbacks and not having a giant code block, then you can try to use async/await instead along with the new promise based reading methods on the blob itself (https://developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer)
input.addEventListener('change', async evt => {
const [file] = input.files
if (file) {
const arrayBuffer = await file.slice(28, 7412).arrayBuffer()
const compressed = new Uint8Array(arrayBuffer)
fileBuffer = pako.inflate(compressed)
document.getElementById('Decompress').disabled = false
} else {
// input was cleared
}
})

I'm just starting with JS and I don't really understand how setTimeout works

I am developing a trivia page with a series of questions that I get through an API. When I give to start the game on the main page, I want to redirect me to a second page where the available categories will appear and when I click on them, the questions will appear with multiple answers.
Luckily I have managed to do all this, however, when I switch from one page to another I have not been able to get the categories to appear. They only appear if I am already on that page and I create a button to call the function that displays them.
I had thought of doing this function in this way so that it would switch me to the other page and then load the questions but I have not been able to get it to work.
Does anyone have a solution or know why it is not working?
function get_dataJson() {
let data_json = [];
fetch('https://opentdb.com/api.php?amount=10')
.then(response => response.json())
.then(data => data.results.forEach(element => {
data_json.push(element);
}));
return data_json;
}
let trivial_data = get_dataJson();
function startGame() {
let div_username = document.createElement("div");
let name = document.createElement("h2");
name.innerHTML = document.getElementById("name").value;
div_username.appendChild(name);
let categories = get_categories(trivial_data);
setTimeout("location.href='./game.html'", 1000);
setTimeout(function(){
document.getElementById('nav-game').appendChild(div_username);
show_categories(categories);
},2000);
}
function get_categories(trivial_data) {
let categories = [];
trivial_data.forEach(element => {
categories.push(element.category)
});
console.log(categories);
return categories;
}
function show_categories (categories) {
let div_categories = document.createElement("div");
let count = 0;
categories.forEach ( element => {
let element_category = document.createElement("button");
element_category.innerHTML = element;
element_category.id = count;
element_category.onclick = function() {
get_question(element_category.id);
};
count++;
div_categories.appendChild(element_category);
});
div_categories.className = 'categories';
document.getElementById("categories").appendChild(div_categories);
}
function get_question (pos) {
document.getElementById("categories").style.displays = 'none';
let question = document.createElement("h2");
question.innerHTML = trivial_data[pos].question;
let correct_answer = trivial_data[pos].correct_answer;
let incorrect_answers = trivial_data[pos].incorrect_answers;
let options = incorrect_answers.concat(correct_answer);
options = options.sort();
let div_choices = document.createElement("div");
options.forEach(element => {
let choice = document.createElement('button');
choice.innerHTML = element;
choice.id = 'true' ? element == correct_answer : 'false';
div_choices.appendChild(choice);
});
div_choices.className = 'answers';
document.getElementById("questions").appendChild(question);
document.getElementById("questions").appendChild(div_choices);
}
The first thing you should do is make sure you understand how to use fetch to get data asynchronously
async function get_dataJson() {
const response = await fetch('https://opentdb.com/api.php?amount=10');
const json = await response.json();
return json.results;
}
(async function(){
const trivial_data = await get_dataJson();
console.log(trivial_data);
})()
Then, rather than changing page, just stay on the same page and add/remove/hide elements as necessary - it looks like you have that bit sorted.

How/When to remove child elements to clear search result?

Trying to clear my search result after I submit a new API call. Tried implementing gallery.remove(galleryItems); at different points but to no avail.
A bit disappointed I couldn't figure it out but happy I was able to get a few async functions going. Anyway, here's the code:
'use strict';
const form = document.querySelector('#searchForm');
const gallery = document.querySelector('.flexbox-container');
const galleryItems = document.getElementsByClassName('flexbox-item');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const userSearch = form.elements.query.value; // grab user input
const res = await getRequest(userSearch); // async func that returns a fully parsed Promise
tvShowMatches(res.data); // looks for matches, creates and appends name + image;
form.elements.query.value = '';
});
const getRequest = async (search) => {
const config = { params: { q: search } };
const res = await axios.get('http://api.tvmaze.com/search/shows', config);
return res;
};
const tvShowMatches = async (shows) => {
for (let result of shows) {
if (result.show.image) {
// new div w/ flexbox-item class + append to gallery
const tvShowMatch = document.createElement('DIV')
tvShowMatch.classList.add('flexbox-item');
gallery.append(tvShowMatch);
// create, fill & append tvShowName to tvShowMatch
const tvShowName = document.createElement('P');
tvShowName.textContent = result.show.name;
tvShowMatch.append(tvShowName);
// create, fill & append tvShowImg to tvShowMatch
const tvShowImg = document.createElement('IMG');
tvShowImg.src = result.show.image.medium;
tvShowMatch.append(tvShowImg);
}
}
};
Thanks
Instead of gallery.remove(galleryItems); consider resetting gallery.innerHTML to an empty string whenever a submit event occurs
Like this:
form.addEventListener('submit', async (e) => {
e.preventDefault();
gallery.innerHTML = ''; // Reset here
const userSearch = form.elements.query.value; // grab user input
const res = await getRequest(userSearch); // async func that returns a fully parsed Promise
tvShowMatches(res.data); // looks for matches, creates and appends name + image;
form.elements.query.value = '';
});
I believe this will do it.. you were close.
const galleryItems = document.getElementsByClassName('flexbox-item');
// to remove
galleryItems.forEach(elem => elem.remove() );

Puppeteer blocking variables inside functions

I recently made a quick web scraper using puppeteer as it targets a JS website and want it to send the output that i get inside my console into discord. The thing is that I always get e.g price not defined or so when the script tries to send the web hook onto discord. Thank you all for your help in advance here is my code if someone can help me out please. I mean where should I put my const embed in order for it to work properly.
const puppeteer = require('puppeteer-extra');
// add stealth plugin and use defaults (all evasion techniques)
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
const { Webhook, MessageBuilder } = require('discord-webhook-node');
const hook = new Webhook("https://discordapp.com/api/webhooks/733332015654371361/9VGAVW-BNlf3G4j3L6GhAIDni17yNIVf9gfmf_TNTQafP40LqYvRwhaYZzL_b58kpkkl");
const url = "https://www.asos.com/fr/nike/nike-air-max-270-baskets-triple-noir-ah8050-005/prd/12490103?clr=noir-triple&colourwayid=16391201&SearchQuery=nike air max 270";
puppeteer.use(StealthPlugin());
async function ConfigureBrowser(){
const browser = await puppeteer.launch({ headless: true }); // for test disable the headlels mode,
const page = await browser.newPage();
await page.setViewport({ width: 1000, height: 926 });
await page.goto(url,{waitUntil: 'networkidle2'})
return page;
};
async function Scrape(page) {
// await page.reload();
console.log("start evaluate javascript")
/** #type {string[]} */
var productINFO = await page.evaluate(()=>{
var div = document.querySelectorAll('.core-product-container');
console.log(div) // console.log inside evaluate, will show on browser console not on node console
const productnames = []
div.forEach(element => {
var titleelem = element.querySelector('#aside-content > div.product-hero > h1');
if(titleelem != null){
productnames.push(titleelem.textContent.trim());
} //#aside-content > div.product-hero > h1
});
const productprice = []
div.forEach(element => {
var price = element.querySelector('[class="current-price"]');
if(price != null){
productprice.push(price.textContent.trim());
}
});
const productsizes = []
div.forEach(element => {
var sizes = element.querySelector('[data-id="sizeSelect"]');
if(sizes != null){
productsizes.push(sizes.textContent.trim());
}
// productsizes.forEach()
})
return [productnames, productprice, productsizes]
})
return productINFO;
// const embed = new MessageBuilder()
// .setTitle(productnames)
// .setURL(url)
// .addField('Prix', productprice, true)
// .addField('sizes', productsizes, true)
// .setColor(8008905)
// // .setThumbnail({image})
// .setDescription('Checked')
// //.setImage(image)
// .setFooter('', 'https://cdn.discordapp.com/attachments/720763827658162260/730786942316183603/image0.jpg')
// hook.send(embed);
discoord(productINFO);
console.log(productINFO);
//browser.close()
} ;
async function Monitor() {
let page = await ConfigureBrowser();
await Scrape(page);
// console.log(productINFO);
}
Monitor();

Categories

Resources