Translate Button on website - Saving the users language preference - javascript

So with my limited JavaScript skills I have created a simple translate button. When you click the button it changes the text on the webpage you are on to either English or Chinese.
How would I go about making these changes stay when someone goes to different webpages or even refreshes the page? I have tried experimenting with the localStorage technique but to no luck.
Here is my JS code for the translate button:
// onclick behavior
$('.lang').click('touchstart', function() {
var lang = $(this).attr('id'); // obtain language id
// translate all translatable elements
$('.tr').each(function(i) {
$(this).text(aLangKeys[lang][$(this).attr('key')]);
});
});
// preparing language file
var aLangKeys = new Array();
aLangKeys['en'] = new Array();
aLangKeys['ch'] = new Array();
aLangKeys['en']['home'] = 'Home';
aLangKeys['en']['about'] = 'About Us';
aLangKeys['en']['serv'] = 'Services';
aLangKeys['en']['sem'] = 'Search Engine Marketing';
aLangKeys['en']['webdev'] = 'Website Development';
aLangKeys['ch']['home'] = '首页';
aLangKeys['ch']['about'] = '关于我们';
aLangKeys['ch']['serv'] = '服务';
aLangKeys['ch']['sem'] = '谷歌与雅虎推广';
For local storage I have added in this right under the var = aLangKeys = new array.
localStorage.setItem("aLangKeys", aLangKeys);
var someVarName = localStorage.getItem("aLangKeys");
Thanks!

LocalStorage only allows storing strings so you need to use JSON.stringify() and JSON.parse() when getting and setting.
But first you shouldn't be using new Array() for non numeric keys. What you are really doing is making an array like object when you do that
Change to:
var aLangKeys = {
en :{},
ch: {}
};
// .... other definitions
To set
localStorage.setItem("aLangKeys", JSON.stringify(aLangKeys));
To get
var someVarName = JSON.parse(localStorage.getItem("aLangKeys"));

Related

why my Local Storage show me "object HTMLSpanElement"?

Hello everybody I am relatively new to coding. I have a local storage project in object oriented javascript for reservation data and to display them in a reservation summary.I am currently blocked, I manage to recover the various values ​​with "getItem", but when I want to display them on my html it displays "object HTMLSpanElement".
the only solution I found is to add ".textcontent" at the end of my variables but it doesn't work.
this is my code
class information{
constructor(){
this.StationName = document.getElementById("StationName");
this.name = document.getElementById("name");
this.firstname = document.getElementById("firstname");
this.adresse = document.getElementById("adresse");
this.PlacesTotal = document.getElementById("PlacesTotal");
this.nbrVeloDispo = document.getElementById("nbrVeloDispo");
};
initstorage(){
var StationName = document.getElementById("StationName").textContent;
var name = document.getElementById("name").value;
var firstname = document.getElementById("firstname").value
var adresse = document.getElementById("adresse").textContent;
var PlacesTotal = document.getElementById("PlacesTotal").textContent;
var nbrVeloDispo = document.getElementById("nbrVeloDispo").textContent;
};
initreservation(){
var StationName = localStorage.getItem("StationName");
var name = localStorage.getItem("name");
var firstname = localStorage.getItem("firstname");
var adresse = localStorage.getItem("adresse");
var PlacesTotal = localStorage.getItem("PlacesTotal");
var nbrVeloDispo = localStorage.getItem("nbrVeloDispo");
};
reserver(){
document.getElementById("signature").style.display = "block";
document.getElementById("panneaureservation").style.display = "none";
};
};
document.getElementById("reservation1").innerHTML = StationName;
const stockage = new information();
document.getElementById("reserve").onclick = function() { stockage.initstorage(); stockage.initreservation(); stockage.reserver(); }
Thank you for taking your time to help me.
When you call localStorage.setItem() you are attempting to store a reference to the DOM element itself instead of the content of that element. Since localStorage only stores strings, the object implicitly gets its .toString() method called on it and a string representation of the object's type and element name is what gets stored.
Here's an example of what's happening (described above):
console.log(document.querySelector("div").toString());
<div>My div element</div>
Once that happens, you can't extract the reference later because all you have is the string name of the object.
You didn't show that code, but that's what needs to be updated. It should store the string value that you will want to get later. Something like this:
localStorage.setItem("StationName", document.getElementById("StationName").textContent);
localStorage.setItem("name", document.getElementById("name").value);
localStorage.setItem("firstname", document.getElementById("firstname").value);
localStorage.setItem("adresse", document.getElementById("adresse").textContent);
localStorage.setItem("PlacesTotal", document.getElementById("PlacesTotal").textContent);
localStorage.setItem("nbrVeloDispo", document.getElementById("nbrVeloDispo").textContent);
Where you set the .textContent of non-form field DOM elements and the .value of form field DOM elements. And, of course, you don't want this code to run against form field data until the form has been completed.

Condensing repetitive code with google scripts

Pretty new to all this but have a simple script to pull API info and put into google sheets. I want to pull the top 20 coins but I'm unsure of how to do it as a ??'function'?? to limit the amount of code required presently especially since only 'XXX' is basically changing. Thanks in advance
var urlBTC='https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d&limit=2';
var responseBTC = UrlFetchApp.fetch(urlBTC,{'muteHttpExceptions': true});
var jsonBTC = responseBTC.getContentText();
var parseBTC = JSON.parse(jsonBTC);
sheetBTC.getRange(3,3).setValue(parseBTC[0][6]);
var sheetETH = sh.getSheetByName("ETH");
var urlETH='https://api.binance.com/api/v3/klines?symbol=ETHUSDT&interval=1d&limit=2';
var responseETH = UrlFetchApp.fetch(urlETH,{'muteHttpExceptions': true});
var jsonETH = responseETH.getContentText();
var parseETH = JSON.parse(jsonETH);
sheetETH.getRange(3,3).setValue(parseETH[0][6]);
}```
var coins = ['ETHUSDT','BTCUSDT']
function getCoin(){
coins.forEach(coin => {
let url = 'https://api.binance.com/api/v3/klines?symbol='+ coin
+ '&interval=1d&limit=2'
//do the other stuff
})
}
Hope this helps set you off in the right direction.
Basically we store the symbols as an array loop through and create a url for that, in the 'do something' put in your other code for handling the req. watch out for rate limits

Javascript Object with a variable

I'm building a basic game with NSEW navigation.
Each NSEW button changes the current location's number, 1,2,3,etc.
Each location has an object that's intended to be associated with it, named loc1,loc2,loc3,etc.
Each object has a description that needs to be displayed, loc1.desc, loc2.desc, etc.
My display function is working, as is my navigation, BUT...
I'm TRYING to pass the loc#.desc value corresponding to the correct current location into the function. (This is Javascript, btw). Currently, it looks like this:
function nextLoc(dir) {
var newLoc = nav[currentLoc][dir];
currentLoc=newLoc;
displayMessage(loc[currentLoc].desc);}
I want it to input the current location's number and pass that to the displayMessage function. I've tried it a ton of different ways, but it still does NOT print the description. If I hard code the number (loc2.desc) or just pass currentLoc, it works, returning the correct object description or the currentLoc number. I've also tried:
loc+[currentLoc]+.desc
Is there a way to do this? I've searched and tried all the different ways to find this but I can't find this specific issue and, at this point, I'm just lost! Any help is greatly appreciated!!
In answer to comments, here's the whole js file:
//Location prototype
function Location(id, desc){
this.id = id;
this.desc = desc;}
//Location objects
var loc2 = new Location(2, "Circus");
var loc1 = new Location (1, "Zoo");
var loc0 = new Location (0,"You entered the park here");
var currentLoc = 0;
var EAST = 0;
var WEST = 1;
var NORTH = 2;
var nav = [ // E,W,N,S
/*Current Location*/
/* 0 */ [2,1,4,-1],
/* 1 */ [0,-1,3,-1],
/* 2 */ [-1,0,5-1],
/* 3 */ [4,-1,-1,1],
/* 4 */ [5,3,-1,0],
/* 5 */ [-1,4,-1,2],
];
// Directional Button Event Handlers
function btnEast_click() {nextLoc(EAST);}
function btnWest_click() {nextLoc(WEST);}
function btnNorth_click() {nextLoc(NORTH);}
function nextLoc(dir) {
var newLoc = nav[currentLoc][dir];
currentLoc=newLoc;
displayMessage(loc[currentLoc].desc);}
// Utility Function(s)
function displayMessage(msg) {
var target = document.getElementById("taMain");
target.value = msg + "\n\n" + target.value;
}
You were quite close to being able to do named-lookups in a map object. Rather than creating a bunch of independent locations (which in a browser, end up as properties of the window object, so there was an avenue that I've chosen not to pursue that would've let you use them.
What I'm doing below is creating an object for the static locations. Another approach would be to use notation like this, which would actually result in the same behavior but might be easier to understand what's going on:
var locations = [];
locations['loc2'] = new Location(2, "Circus");
locations['loc1'] = new Location(1, "Zoo");
locations['loc0'] = new Location(0, "You entered the park here.");
Also workable would be removing the 'loc' prefix on your keys, then you could write things like this:
var locations = [];
locations.add = function(id, desc){ locations[id] = new Location(id, desc)}
locations.add(0, "You entered the park here.")
// and your navigation method looks like this then
function nextLoc(dir){
var newLoc = nav[currentLoc][dir];
currentLoc=newLoc;
displayMessage(locations[currentLoc].desc);
}
Another form which resembles what you've done so far
var locations = {
loc2 : new Location(2, "Circus"),
loc1 : new Location (1, "Zoo"),
loc0 : new Location (0,"You entered the park here")
};
function nextLoc(dir) {
var newLoc = nav[currentLoc][dir];
currentLoc="loc"+newLoc;
displayMessage(locations[currentLoc].desc);}

How to read javascript variable using Selenium?

I'm learning to read javascript variable using Selenium WebDriver (latest version). Sometimes it works, sometimes not. Below is my try on whoscored.com and it keeps showing error
using (IWebDriver driver = new ChromeDriver())
{
driver.Navigate().GoToUrl("http://www.whoscored.com/Regions/81/Tournaments/3/Germany-Bundesliga");
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
var tournament = wait.Until(ExpectedConditions.ElementExists(By.Id("tournament-fixture-wrapper")));
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
var obj = (object)js.ExecuteScript("return window.allRegions;"); //always return error 'Additional information: Unable to cast object of type 'System.Int64' to type 'System.String'.
}
I think you should change
var obj = (object)js.ExecuteScript("return window.allRegions;");
to
List<object> list = js.ExecuteScript("return window.allRegions;") as List<object>;
since, return window.allRegions; does not return a string but array of objects.
Edit
Just went through the page and looks like window.allRegions returns a List of json objects. And, does feel like creating a list of json object can be unwanted overwhelming of programming. I suggest you to narrow down the goal either with modifying the javascript or performing some filtering like following.
var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(30));
var tournament = wait.Until(ExpectedConditions.ElementExists(By.Id("tournament-fixture-wrapper")));
IJavaScriptExecutor js = _driver as IJavaScriptExecutor;
//getting count of regions
long count = (long)js.ExecuteScript("return window.allRegions.length;");
for (int i = 0; i < count; i++)
{
//grab the name of countries if that's what you wanted
string name = js.ExecuteScript("return window.allRegions[" + i + "].name;") as string;
Console.WriteLine(name);
}
Print:
Africa
Albania
Algeria
...
Zambia
Zimbabwe

dispatchMessage and associative arrays

I have a problem delivering assiciative arrays to an injected script.
Global.html
var settings = new Array();
settings["accountID"] = safari.extension.settings.getItem("accountID");
settings["accountName"] = safari.extension.settings.getItem("accountName");
settings["accountEmail"] = safari.extension.settings.getItem("accountEmail");
safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("settingsArray", settings);
script.js
switch (msgEvent.name) {
case "settingsArray":
var settings = new Array();
settings = msgEvent.message;
console.log("accountID: " + settings["accountID"]);
break;
When I do it with "normal" arrays, it works fine!
But when delivering associative arrays, I always get "undefined" when calling eg. settings["accountID"]
Does anyone have an idea what's wrong?
You're using arrays when you should be using objects.
var settings = new Array(); // Wrong
var settings = {}; // Right (and better than "new Object()")
You are unnecessarily using the string form of property access.
settings["accountID"] = …; // Works, but too much typing
settings.accountID = …; // Exact same functionality
You only need to use the bracket notation when getting/setting property values if the property name is not a valid JavaScript identifier (e.g. foo["holy!*#$! it works"] = true) or if you need to construct the property name from a variable (e.g. foo["account"+n] = "active";).
You are creating new objects and then throwing them away.
var settings = new Array(); // Makes a new array referenced by a variable
settings = msgEvent.message; // Discards the array and changes the variable
// to reference a new object

Categories