javascript string replace unicode troubles - javascript

I want to be able to transliterate names into different languages. I'm starting with Armenian.
My html is like this:
<input type="text" class="name"></input><br>
<p class="transliterated"></p>
<button id="button">transliterate!</button>
My javascript is like this:
var buttonEl = document.getElementById("button");
buttonEl.addEventListener("click", getArmenian);
function getArmenian() {
var inputEl = document.getElementsByClassName("name");
var outputEl = document.getElementsByClassName("transliterated");
for (var i = 0; i < inputEl.length; i++) {
var nameEl = inputEl[i].value;
var ayb = '&#x561';
var ben = '&#x562';
var nameEl = nameEl.replace(/a/gi, ayb);
var nameEl = nameEl.replace(/b/gi, ben);
outputEl[i].innerHTML = nameEl;
}
}
In the above example, I'm picking out the letters a and b, and replacing them with the Armenian characters 'ayb' and 'ben', respectively.
So far so good.
The pickle starts here: I've defined variables for all the letters of the Armenian alphabet the same way I did for 'ayb' and I used replace to replace the respective letter of the English alphabet. This is not a sophisticated transliteration at this point.
The 'x' is problematic, since each code contains an 'x' so I just search and replace the 'x' first, and that mini-problem is solved.
But this thing doesn't distinguish between between 'r' and 'R' when searching. How can I fix that? Right now, if I transliterate 'Rob' it gives me '&#x57C + &#x585 + &#x562' which I am happy with, but I didn't knowingly program it to recognize the capital letter 'R'.
Once I do that, how do I keep this thing from replacing the 'C' in '&#x57C' which is the letter 'ra'?

As NULL-POINTER mentioned, it is because if your "i" in the regex pattern. I think that you will have a lot of these "problematic" occurrences doing it via a regex, as multiple letters might have this exact problem. I'd recommend instead using a hash to represent the transliteration. I have made an example that maps a, b, and c to x, y, and z. Of course you'd want to write your own hash, but here's the gist of the idea:
var hash = {
a: "x",
b: "y",
c: "z"
};
var str = "abcdddcba";
// first, do a split so each letter is a part of the array
var translate = str.split("")
// then when you have an array of letters, you can map it to the new values in the hash, and default it to itself if no match is found
.map((letter) => hash[letter] || letter)
// next, join all of the letters back together
.join("");
You can check this out on a fiddle I made for you: https://jsfiddle.net/fwkr94Le/

Related

Regex to identify specific strings and not just keys

I am creating a calculator for my website and I am using the eval()
function, the issue is that I have a whitelist of allowed terms and
keys and I want to make sure only terms that are specifically in that
order are let through. For example, if I have a term called SQRT, I
would like terms that are only SQRT to be let through, right now I
have the problem that all instances of the letters in SQRT are also
let through, for example T
var input1 = "0";
var keywords = ["sqrt", "sin", "cos", "tan", "log","exp"];
function evalue(){
var keys = [];
keywords.forEach(element => {
keys.push("{^"+ element +"$}");
});
var whitelist = new RegExp("[^-()/1234567890*+." + keys.join() + "]", "g");
input1 = document.getElementById("calcInput1").value;
input1 = input1.replace(whitelist, '');
keywords.forEach(element => {
var elSearch = new RegExp(element, "g");
input1 = input1.replace(elSearch, "Math."+element)
});
input1 = eval(input1);
input1 = (Math.round((input1*100)))/100;
document.getElementById("calcResult").innerHTML=input1;
console.log(input1);
}
I thought that by separating the terms into {^$}, they would only find those specific terms and let them through.
[^xxxx] is not character inside, if you put there any word it will use characters from the word.
I would solve your problem with tokenizing the string using the keywords and numbers and filtering out what don't match:
var keywords = ["sqrt", "sin", "cos", "tan", "log","exp"];
var re = new RegExp('(' + keywords.join('|') + '|[0-9]+)');
var input = document.querySelector('input');
document.querySelector('button').addEventListener('click', function() {
var text = input.value.split(re).filter(Boolean).map(function(token) {
if (token.match(re)) {
return token;
}
return '';
}).join('');
console.log(text);
});
<input/>
<button>eval</button>
And suggestion if you want proper calculator you probably will need a parser, you can use some parser generator. I've wrote an article about different parser generators in JS (but it's in Polish), there are example codes and you can use google translate (link with translation). 5 parser generators in JavaScript (here is original post 5 Parserów i Generatorów Parserów w JavaScript use this link to check the example source code, because Google was converting the code into one line).

Checking user input against an array, act as a guess Javascript

I am a new aspiring dev and I am trying to figure out how to build a game of hangman using vanilla js only. I have put together a key event listner, and have got it to console log the inputs. I have also got it to print the letters pushed into a "letters guessed" array.
document.addEventListener("keypress", letterPressed);
function letterPressed(event) {
var letter = String.fromCharCode(event.keyCode);
guessedLetters.push(letter);
document.getElementById("lettersGuessed").innerHTML = guessedLetters;
console.log(guessedLetters)
}
I also have an array of choices of words
var wordList = ["Ravens", "Cardinals", "Falcons", "Bills",
"Panthers", "Bears", "Bengals", "Browns", "Cowboys",
"Broncos", "Lions", "Packers", "Texans", "Colts",
"Jaguars", "Cheifs", "Chargers", "Rams",
"Dolphins", "Vikings", "Patriots", "Saints",
"Giants", "Jets", "Raiders", "Eagles", "Steelers",
"Forty Niners", "Seahawks", "Buccaneers", "Titans",
"Redskins"];
and a for loop picking the random word from this array, converting it to "_" strings in the length of the word, and printing it to the html document in a div id of "spaces".
var wordBlanks = [];
var guessedLetters = [];
var randomWord = wordList[Math.floor(Math.random() * wordList.length)];
for (var i = 0; i < randomWord.length; i++) {
wordBlanks[i] = "_";
console.log(wordBlanks,randomWord);
document.getElementById("spaces").innerHTML = wordBlanks.join(" ");
};
Where would I even want to go from here? I want to check input from the keystrokes (or the letters guessed array, im not sure which would be best) against the word thats chosen and have the "_" strings reveal the correct guesses when guessed correctly.
My question is more regarding pointing me in the right direction. So, I can properly teach myself. Any words of advice?
Thank you!
You'll have to come to terms with the upper/lowercase issue first, but after that, something like this will work:
const randomWord = "BEARS";
const guessedLetters = ["S", "O", "E"];
const wordBlanks = randomWord.split('')
.map(letter => guessedLetters.indexOf(letter) >= 0 ? letter : "_")
.join(' ');
console.log(wordBlanks);
Instead of putting into the guessedLetters array, try to see if the presses letter can be found in the randomWord.
If so, find the position of the letter and let it replace the appropriate _ space in the wordBlank array.
Something like:
function letterPressed(event) {
var letter = String.fromCharCode(event.keyCode);
if (randomWord.indexOf(letter) >= 0)
wordBlank[(randomWord.indexOf(letter)] = letter;
console.log(wordBlank);
}
Note that a letter may have multiple occurences in a word.

Grab strings before and after inner string in regex Javascript

I have a string like this:
20 EQUALS 'Value goes here'
I want to split it up into 3 separate strings:
conditionField = 20
conditionOperation = 'EQUALS'
conditionValue = 'Value goes here'
I tried this to get the Condition Field:
var conditionField = condition.replace(/(.*)(.*EQUALS)/, '$1');
But it get's the beginning and the end.
I'm having trouble splitting it up and dealing with the white space and spaces in the value.
Your question would actually be a bit of challenge if you wanted to arbitrarily extract quoted terms along with individual words. But since you appear to have a rather fixed structure, starting with a single number, then a single word command, followed by a third term, we can use the following regex pattern here:
([^\\s]*)\\s+([^\\s]*)\\s+(.*)
Each term in parentheses above will be made available as a capture group after the match has been run. In this case, I just blanket everything after the first two terms together.
var string = "20 EQUALS 'Value goes here'";
var re = new RegExp("([^\\s]*)\\s+([^\\s]*)\\s+(.*)");
match = re.exec(string);
if (match != null) {
console.log(match[1])
console.log(match[2])
console.log(match[3])
}
Try this :
var data = '20 EQUALS 30';
var a = data.split(/(\d*) ([a-zA-Z]*) (\d*)/g);
conditionField = a[1];
conditionOperation = a[2];
conditionValue = a[3];

1 string that are 2 words with no whitespace

I'm doing a tracking application for my company and I really need your help
I've got some strings that display it wrong
I'll get the postcode/zipcode and the city name and the "function" (for example distrubition basis)
The string I get is something like that (it's swiss and the format is postcode cityname function)
place = "5506 MägenwilDistributionsbasis";
now postcode is "5506"
cityname is "Mägenwil"
function is "Distributionsbasis"
my question is how can I split the cityname and function (for this example now)?
is it possible to do it with regex or an if statement?
You can split the string using the following regexp:
var myString = "5506 MägenwilDistributionsbasis";
var units = /(\d+ )([A-Z][^A-Z]+)(.+)/g.exec(myString);
Check out contents of array units: there you see units[0] is the whole string, and units[1], units[2], units[3] are what you need.
Note According to comments I must say, it's just a draft for possible solution to let you understand how to start working on the problem in JS. So when you will test your application with more complicated city names and function names in the "magic string", try to figure out what regexp fits your purposes perfectly, because ([A-Z][^A-Z]+) definitly will not match all the known city names.
You could implement that in the most primitive way. Something like this:
place = "5506 MägenwilDistributionsbasis";
var codeAndNameAndFunction = place.split(" ");
var code = codeAndNameAndFunction[0];
var nameAndFunction = codeAndNameAndFunction[1];
var startOfTheFunction;
for (var i = 1, len = nameAndFunction.length; i < len; i++) {
myCharacter = nameAndFunction.charCodeAt(i);
if (myCharacter >= 65 && myCharacter <= 90) {
startOfTheFunction = i;
break;
}
}
var name = nameAndFunction.slice(0, startOfTheFunction);
var functionName = nameAndFunction.slice(startOfTheFunction,nameAndFunction.length);
This is a slight modification of Florian Peschka's answer:
You can split the string using the following regexp:
var myString = "5506 Yverdon-les-BainsDistributionsbasis";
var units = /(\d+ )(.+)([A-Z][^A-Z]+)/g.exec(myString);
Check out contents of array units: there you see units[0] is the whole string, and units[1], units[2], units[3] are what you need.
Note that this will only work if the "function" name is always in the form of Capital Letter followed by Non-capital letters.

Adding Dashes to a number without many lines of code

I have a number returned from the database
e.g.
329193914
What I would like to do it simply be able to just insert dashes every 3 characters.
e.g.
329-193-914
I was looking at regex, replace and slice , slice I had a hard time with as a lot of example are like f.value and i'm not passing in "this" (entire element)
if your number can be treated as a string:
var str = '329193914';
var arr = str.match(/.{3}/g); // => ['329', '193', '914']
var str2 = arr.join('-'); // => '329-193-914'

Categories