This question already has answers here:
How to convert a string of hex values to ASCII
(3 answers)
Decode UTF-8 with Javascript
(15 answers)
Closed 1 year ago.
How to decode from:
\x6a\x61\x76\x61\x73\x63\x72\x69\x70\x74\x3a\x61\x6c\x65\x72\x74\x28313\x29
to:
javascript:alert(313)
Does anyone know about coding please guide me, I will appreciate you a lot!
Thank you!
You could write a simple parser that converts Unicode code-points to equivalent characters.
const main = () => {
const convertBtn = document.querySelector('.convert');
convertBtn.addEventListener('click', onConvert);
triggerEvent(convertBtn, 'click');
};
const onConvert = e => {
const input = document.querySelector('.input');
const output = document.querySelector('.output');
output.value = parseUnicodeString(input.value);
};
const parseUnicodeString = unicodeSring => {
let result = '', buffer = null;
for (let i = 0; i < unicodeSring.length; i++) {
if (unicodeSring[i] === 'x') {
buffer = '';
} else if (/[0-9a-f]/.test(unicodeSring[i])) {
if (buffer != null) {
if (buffer.length === 1) {
result += parseCodePoint(buffer + unicodeSring[i]);
buffer = null;
} else {
buffer += unicodeSring[i];
}
} else {
result += unicodeSring[i];
}
}
}
if (buffer != null && buffer.length > 0) {
result += parseCodePoint(buffer);
}
return result;
}
const parseCodePoint = codePoint =>
String.fromCodePoint(parseInt(codePoint, 16));
const triggerEvent = (el, eventName, data) => {
let event;
if (window.CustomEvent && typeof window.CustomEvent === 'function') {
event = new CustomEvent(eventName, {detail: data});
} else {
event = document.createEvent('CustomEvent');
event.initCustomEvent(eventName, true, true, data);
}
el.dispatchEvent(event);
};
main();
body,html{width:100%;height:100%;margin:0;padding:0;background:#000;color:#fff}body{display:flex;flex-direction:column}button{background:#c46;border:thin solid #d26;color:#eee;padding:.125em;font-weight:700;cursor:pointer}button:hover{background:#f47;color:#fff}textarea{flex:1;background:#222;color:#eee;resize:none;border:none;outline:0;padding:.25em}
<textarea class="input">\x6a\x61\x76\x61\x73\x63\x72\x69\x70\x74\x3a\x61\x6c\x65\x72\x74\x28313\x29</textarea>
<button class="convert">Convert</button>
<textarea class="output">
</textarea>
If you combine String.prototype.replace with a regular expression, you can simply the logic above into a one-liner.
const main = () => {
const convertBtn = document.querySelector('.convert');
convertBtn.addEventListener('click', onConvert);
triggerEvent(convertBtn, 'click');
};
const onConvert = e => {
const input = document.querySelector('.input');
const output = document.querySelector('.output');
output.value = parseUnicodeString(input.value);
};
const parseUnicodeString = unicodeSring =>
unicodeSring.replace(/\\x([0-9a-f]{2})/ig, (match, codePoint) =>
String.fromCodePoint(parseInt(codePoint, 16)));
const triggerEvent = (el, eventName, data) => {
let event;
if (window.CustomEvent && typeof window.CustomEvent === 'function') {
event = new CustomEvent(eventName, {detail: data});
} else {
event = document.createEvent('CustomEvent');
event.initCustomEvent(eventName, true, true, data);
}
el.dispatchEvent(event);
};
main();
body,html{width:100%;height:100%;margin:0;padding:0;background:#000;color:#fff}body{display:flex;flex-direction:column}button{background:#c46;border:thin solid #d26;color:#eee;padding:.125em;font-weight:700;cursor:pointer}button:hover{background:#f47;color:#fff}textarea{flex:1;background:#222;color:#eee;resize:none;border:none;outline:0;padding:.25em}
<textarea class="input">\x6a\x61\x76\x61\x73\x63\x72\x69\x70\x74\x3a\x61\x6c\x65\x72\x74\x28313\x29</textarea>
<button class="convert">Convert</button>
<textarea class="output">
</textarea>
Related
I am developing a "Battleship" game with two grids made up of divs and am currently attempting to add a click event listener to all of the divs.
The issue that I am having is that the event listener is being repeatedly triggered (until every single div has been clicked) when I refresh my page and I can't understand why...
Here's the event listener in question:
let aiGridCells = document.querySelectorAll(".ai-grid__game-cell");
aiGridCells.forEach(cell => {
cell.addEventListener("click", humanPlayer.humanAttack(cell.getAttribute('data-ai'),aiPlayer))
});
Where humanPlayer is an object that has been generated by a factory function:
const humanPlayer = playerFactory('human');
import gameboardFactory from './gameboardFactory';
const playerFactory = (name) => {
const playerBoard = gameboardFactory();
const humanAttack = (cell, player) => { // Where player is opponent
if (player.playerBoard.gameBoard[cell].id !== 'miss') {
player.playerBoard.receiveAttack(cell);
};
};
const aiAttack = (player) => { // Where player is opponent
const availableCells = [];
for (let i = 0; i < player.playerBoard.gameBoard.length; i++) {
if (player.playerBoard.gameBoard[i].id === null) {
availableCells.push(i);
};
};
const attackCell = Math.floor(Math.random() * availableCells.length);
player.playerBoard.receiveAttack(attackCell);
};
return {
name,
playerBoard,
humanAttack,
aiAttack
}
};
export default playerFactory;
and gameboardFactory is:
import shipFactory from './shipFactory';
const gameboardFactory = () => {
const gameBoard = [];
const shipYard = [];
const init = () => {
for (let i = 0; i<100; i++) {
gameBoard.push({id: null})
};
};
const checkValidCoordinates = (direction, start, end) => {
if (direction === 'horizontal') {
if ((start <= 9) && (end <= 9)) {
return true;
} else {
let newStart = (start/10).toString(10);
let newEnd = (end/10).toString(10);
if ((newStart.charAt(0)) === (newEnd.charAt(0))) {
return true;
};
};
} else {
if ((start <= 9) && (end <= 9)) {
return false
} else if (start <= 9) {
let newStart = start.toString(10);
let newEnd = end.toString(10);
if ((newStart.charAt(0)) === (newEnd.charAt(1))) {
return true;
};
} else {
let newStart = start.toString(10);
let newEnd = end.toString(10);
if ((newStart.charAt(1)) === (newEnd.charAt(1))) {
return true;
};
};
};
return false
};
const checkIfShipPresent = (direction, start, end) => {
if (direction === 'horizontal') {
for (let i = start; i <= end; i++) {
if (gameBoard[i].id !== null) {
return true;
}
};
return false;
} else {
for (let i = start; i <= end; i += 10) {
if (gameBoard[i].id !== null) {
return true;
}
};
return false;
};
};
const placeShip = (id, direction, start, end) => {
if (!checkValidCoordinates(direction, start, end)) {
return;
};
if (checkIfShipPresent(direction, start, end)) {
return;
};
const newShip = [];
if (direction === 'horizontal') {
for (let i = start; i <= end; i++) {
gameBoard[i].id = id;
newShip.push(i);
};
} else {
for (let i = start; i <= end; i += 10) {
gameBoard[i].id = id;
newShip.push(i);
};
};
shipYard.push(shipFactory(id, newShip));
};
const receiveAttack = (cell) => {
console.log(cell)
if (gameBoard[cell].id !== null) {
const attackedShip = shipYard.filter((ship) => {
return ship.id === gameBoard[cell].id;
})[0];
if (!attackedShip.hits.includes(cell)) {
attackedShip.hits.push(cell);
};
} else {
gameBoard[cell].id = 'miss';
};
};
const checkIfAllShipsSunk = () => {
let allShipsSunk = true;
shipYard.forEach((ship) => {
if (ship.isSunk() === false) {
allShipsSunk = false;
};
});
return allShipsSunk;
};
if (gameBoard.length === 0) {
init();
};
return {
gameBoard,
placeShip,
receiveAttack,
shipYard,
checkIfAllShipsSunk
};
};
export default gameboardFactory;
I'm completely lost to what the issue could be and have tried countless things to rectify it. Any suggestions would be hugely appreciated.
Thank you!
You trying to add actual function call as listener here:
let aiGridCells = document.querySelectorAll(".ai-grid__game-cell");
aiGridCells.forEach(cell => {
cell.addEventListener("click", humanPlayer.humanAttack(cell.getAttribute('data-ai'),aiPlayer))
});
So on your event listener initialization you actually call your function instead of passing it as a listener.
You can pass it like this instead:
aiGridCells.forEach(cell => {
cell.addEventListener("click", () => humanPlayer.humanAttack(cell.getAttribute('data-ai'),aiPlayer))
});
I have problem with my trampoline based function that stringify lisp list. Here is the code:
function Pair(car, cdr) {
this.car = car;
this.cdr = cdr;
}
const nil = new function Nil() {};
// ----------------------------------------------------------------------
Pair.fromArray = function(array) {
var result = nil;
var i = array.length;
while (i--) {
let car = array[i];
if (car instanceof Array) {
car = Pair.fromArray(car);
}
result = new Pair(car, result);
}
return result;
};
// ----------------------------------------------------------------------
function Thunk(fn, cont = () => {}) {
this.fn = fn;
this.cont = cont;
}
// ----------------------------------------------------------------------
Thunk.prototype.toString = function() {
return '#<Thunk>';
};
// ----------------------------------------------------------------------
function trampoline(fn) {
return function(...args) {
return unwind(fn.apply(this, args));
};
}
// ----------------------------------------------------------------------
function unwind(result) {
while (result instanceof Thunk) {
const thunk = result;
result = result.fn();
if (!(result instanceof Thunk)) {
thunk.cont();
}
}
return result;
}
// ----------------------------------------------------------------------
// original function have different data types here
// with simplified version this is fine
function toString(x) {
return x.toString();
}
// ----------------------------------------------------------------------
const pair_to_string = (function() {
const prefix = (pair, rest) => {
var result = [];
if (pair.ref) {
result.push(pair.ref + '(');
} else if (!rest) {
result.push('(');
}
return result;
};
const postfix = (pair, rest) => {
if (!rest || pair.ref) {
return [')'];
}
return [];
};
return trampoline(function pairToString(pair, quote, extra = {}) {
const {
nested,
result = [],
cont = () => {
result.push(...postfix(pair, nested));
}
} = extra;
result.push(...prefix(pair, nested));
let car;
if (pair.cycles && pair.cycles.car) {
car = pair.cycles.car;
} else {
car = toString(pair.car, quote, true, { nested: false, result, cont });
}
if (car !== undefined) {
result.push(car);
}
return new Thunk(() => {
if (pair.cdr instanceof Pair) {
if (pair.cycles && pair.cycles.cdr) {
result.push(' . ');
result.push(pair.cycles.cdr);
} else {
if (pair.cdr.ref) {
result.push(' . ');
} else {
result.push(' ');
}
return pairToString(pair.cdr, quote, {
nested: true,
result,
cont
});
}
} else if (pair.cdr !== nil) {
result.push(' . ');
result.push(toString(pair.cdr, quote));
}
}, cont);
});
})();
// ----------------------------------------------------------------------
Pair.prototype.toString = function(quote) {
var result = [];
pair_to_string(this, quote, {result});
return result.join('');
};
// ----------------------------------------------------------------------
function range(n) {
return new Array(n).fill(0).map((_, i) => i);
}
// ----------------------------------------------------------------------------
function markCycles(pair) {
var seen_pairs = [];
var cycles = [];
var refs = [];
function visit(pair) {
if (!seen_pairs.includes(pair)) {
seen_pairs.push(pair);
}
}
function set(node, type, child, parents) {
if (child instanceof Pair) {
if (parents.includes(child)) {
if (!refs.includes(child)) {
refs.push(child);
}
if (!node.cycles) {
node.cycles = {};
}
node.cycles[type] = child;
if (!cycles.includes(node)) {
cycles.push(node);
}
return true;
}
}
}
const detect = trampoline(function detect_thunk(pair, parents) {
if (pair instanceof Pair) {
delete pair.ref;
delete pair.cycles;
visit(pair);
parents.push(pair);
var car = set(pair, 'car', pair.car, parents);
var cdr = set(pair, 'cdr', pair.cdr, parents);
var thunks = [];
if (!car) {
detect(pair.car, parents.slice());
}
if (!cdr) {
const cdr_args = [pair.cdr, parents.slice()];
return new Thunk(() => {
return detect_thunk(...cdr_args);
});
}
}
});
function mark_node(node, type) {
if (node.cycles[type] instanceof Pair) {
const count = ref_nodes.indexOf(node.cycles[type]);
node.cycles[type] = `#${count}#`;
}
}
detect(pair, []);
var ref_nodes = seen_pairs.filter(node => refs.includes(node));
ref_nodes.forEach((node, i) => {
node.ref = `#${i}=`;
});
cycles.forEach(node => {
mark_node(node, 'car');
mark_node(node, 'cdr');
});
}
// ----------------------------------------------------------------------
// this works fine
//console.log(Pair.fromArray([[[range(8000), range(10)]]]).toString());
var data = new Pair(1, new Pair(new Pair(2, nil), new Pair(3, nil)));
data.cdr.car.cdr = data.cdr;
data.cdr.cdr.cdr = data;
markCycles(data)
console.log(data.toString());
console.log("#0=(1 . #1=((2 . #1#) 3 . #0#)) - valid");
The problem is the last parenthesis is missing, I'm not sure how I should use continuation in trampoline to fix the issue.
Here is the code that was working without trampoline:
// ----------------------------------------------------------------------
Pair.prototype.toString = function(quote, rest) {
var arr = [];
if (this.ref) {
arr.push(this.ref + '(');
} else if (!rest) {
arr.push('(');
}
var value;
if (this.cycles && this.cycles.car) {
value = this.cycles.car;
} else {
value = toString(this.car, quote, true);
}
if (value !== undefined) {
arr.push(value);
}
if (this.cdr instanceof Pair) {
if (this.cycles && this.cycles.cdr) {
arr.push(' . ');
arr.push(this.cycles.cdr);
} else {
if (this.cdr.ref) {
arr.push(' . ');
} else {
arr.push(' ');
}
const cdr = this.cdr.toString(quote, true);
arr.push(cdr);
}
} else if (this.cdr !== nil) {
arr = arr.concat([' . ', toString(this.cdr, quote, true)]);
}
if (!rest || this.ref) {
arr.push(')');
}
return arr.join('');
};
I have two cases that should work first big list (8000 elements) and small cycle. With the code in stack snippet it work with long list but not with cycles without the trampoline it overflow the stack on big list. Also it's lisp so it need to work any any tree not only linked list.
EDIT: if you try to answer please at least don't change the data structures. It need to be Pair class with car and cdr and cycles need to be calculated before they are converted to string. So it work with multiple functions that check if data in memory is cycle.
This is what I would do.
const pure = value => ({ constructor: pure, value });
const bind = (monad, arrow) => ({ constructor: bind, monad, arrow });
const thunk = eval => ({ constructor: thunk, eval });
function evaluate(expression) {
let expr = expression;
let stack = null;
while (true) {
switch (expr.constructor) {
case pure:
if (stack === null) return expr.value;
expr = stack.arrow(expr.value);
stack = stack.stack;
break;
case bind:
stack = { arrow: expr.arrow, stack };
expr = expr.monad;
break;
case thunk:
expr = expr.eval();
}
}
}
const monadic = func => thunk(() => {
const gen = func();
function next(data) {
const { value, done } = gen.next(data);
return done ? value : bind(value, next);
}
return next(undefined);
});
class Pair {
constructor(car, cdr) {
this.car = car;
this.cdr = cdr;
}
static fromArray(array) {
const loop = (array, index) => monadic(function* () {
if (index === array.length) return pure(null);
const item = array[index];
const car = Array.isArray(item) ? yield loop(item, 0) : item;
const cdr = yield loop(array, index + 1);
return pure(new Pair(car, cdr));
});
return evaluate(loop(array, 0));
}
duplicates() {
const visited = new WeakSet();
const result = new WeakSet();
const loop = pair => monadic(function* () {
if (visited.has(pair)) {
result.add(pair);
} else {
visited.add(pair);
const { car, cdr } = pair;
if (car instanceof Pair) yield loop(car);
if (cdr instanceof Pair) yield loop(cdr);
}
return pure(result);
});
return evaluate(loop(this));
}
toString() {
let result = "";
const duplicates = this.duplicates();
const visited = [];
const loop = (pair, end) => monadic(function* () {
const index = visited.indexOf(pair);
if (index < 0) {
const duplicate = duplicates.has(pair);
if (duplicate) {
const last = visited.push(pair) - 1;
result += end ? ` . #${last}=(` : `#${last}=(`;
} else result += end ? " " : "(";
const { car, cdr } = pair;
if (car instanceof Pair) yield loop(car, false);
else result += JSON.stringify(car);
if (cdr instanceof Pair) yield loop(cdr, true);
else if (cdr === null) result += ")";
else result += ` . ${JSON.stringify(cdr)})`;
if (duplicate && end) result += ")";
} else {
result += end ? ` . #${index}#)` : `#${index}#`;
}
return pure(result);
});
return evaluate(loop(this, false));
}
}
const data = new Pair(1, new Pair(new Pair(2, null), new Pair(3, null)));
data.cdr.car.cdr = data.cdr;
data.cdr.cdr.cdr = data;
console.log(data.toString());
const range = length => Array.from({ length }, (x, i) => i);
console.log(Pair.fromArray([[[range(8000), range(10)]]]).toString());
Hope that helps.
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 = "";
}
}
I have a trouble reducing the cognitive complexity here for this function.I tried to separate the contents inside the forEach as another function and by calling it in getCars function but failed. Could anyone please help?
const getCars = (cars, config, types) => {
const {
carName
} = types;
const carObject = {};
const carsRange = () => {}
let carRange = carsRange(cars);
Object.entries(cars).forEach(([key, value]) => {
if (key === 'sedan' && value) {
const carRangeVal = value.split(' ');
const year = carRangeVal[1];
const model = carRangeVal[0].substring(1, 2);
carRange = generateCarRange(year, model);
}
if (key === 'suv' && value) {
const carRangeVal = value.split(' ');
const year = carRangeVal[1];
const model = carRangeVal[0];
carObject['model'] = true;
carRange = checkYear(year, model);
}
if (value) {
carObject[key] = value;
}
});
if (
config.header === 'TEST A' ||
config.header === 'TEST B'
) {
carObject['carName'] = carName[0].id;
}
carObject['configName'] = config.header;
carObject['contractStartDate'] = carsRange[0];
carObject['contractEndDate'] = carsRange[1];
return carObject;
};
console.log(getCars({}, {}, {}));
You could shorten the code in the .forEach function:
[year,model] = value.split(' '); // destructuring assignment
if (key === 'sedan' && value) {
model = model.substring(1, 2);
carRange = generateCarRange(year, model);
}
if (key === 'suv' && value) {
carObject['model'] = true;
carRange = checkYear(year, model);
}
It would be helpful to know the input data.
I have an inkling that you may be better off using .map() instead of .forEach().
Why do you have two functions (generateCarRange() and checkYear()) to get carRange?
(I find it helpful to use Hungarian Notation to always know the type of my variables.)
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());