My first post on here. I have a function on a website whereby a randomly generated French phrase is displayed, challenging the reader to translate it into English in a text box. On clicking on a button, the text entered is compared to all the possible answers (there are multiple correct translations for a given phrase). I've looked around for answers on this but nothing seems to suit my situation.
Here's the jQuery:
var correctAnswer = function(){$('#correctmessage').show('fast');$('#errormessage').hide('fast');}
var wrongAnswer = function(){$('#errormessage').show('fast');$('#correctmessage').hide('fast');}
$('#1').find('button').on('click', function(){
var text = $(this).parent().find('.translatefield').val();
var compareText = "I went to the cinema";
var compareText2 = "I have been to the cinema";
if (text == compareText || text == compareText2) {
correctAnswer();
}
else {
wrongAnswer();
}
});
So I wondered if I can put the 'compare' variables into one variable i.e. 'I went to the cinema OR I have been to the cinema OR etc etc' within one variable for tidiness. But mainly I need to know how I can call that variable within the if so that it also accepts the answer without accented characters and regardless of upper or lower case... I hope this is clear! Thanks for any help you can give, this has been irritating me for a while!
As commented by Mark Holland, use arrays for the compare phrases.
If you are using jQuery anyway, you could use jQuery.inArray().
https://api.jquery.com/jQuery.inArray/
var compareText = ['i went to the cinema','i have been to the cinema'];
if ($.inArray(text.toLowerCase(), compareText)) {
... do stuff
}
To ignore the accents, use a solution like this:
String.prototype.removeAccents = function(){
return this
.replace(/[áàãâä]/gi,"a")
.replace(/[éè¨ê]/gi,"e")
.replace(/[íìïî]/gi,"i")
.replace(/[óòöôõ]/gi,"o")
.replace(/[úùüû]/gi, "u")
.replace(/[ç]/gi, "c")
.replace(/[ñ]/gi, "n")
.replace(/[^a-zA-Z0-9]/g," ");
}
Credits to Luan Castro
Perform a find/match with javascript, ignoring special language characters (accents, for example)?
As mentionned by Mark Holland, arrays would answer your first question.
JS arrays
To ignore accents, a quick search gave me this answer:
Replace accents
And to ignore lower/uppercase, a quick search gave me this answer.
Ignore case
How about setting the strings into one array and iterate this array to compare with the answer?
Related
I am getting an array of objects using JSON and then my goal is to let the user search for a specific login. For this I want them to be able to type a letter and check each object login, if the letter is contained I want to display it.
In order to achieve this I worked on the following code:
var i;
var out="";
var exp=/d/g;
var result = " ";
for(i=0;i<users.length;i++){
result= exp.test(users[i].login);
if(result){
out+= users[i].login+ " ";
}
}
It works fine if I write the regex (in this case d) but once I try putting a variable inside the regex it wont work. How do I create a regex that will take the users input and work with the test function to perform the same task? Or idk if there is a better/more elegant solution for this. I know there are different regex questions already but I didn't find one that helped me.
Appreciate the help!
You're testing a literal string - that string is passed in by the user but it's still literal, not a regex.
So you should try:
if( users[i].login.indexOf(userInput) > -1)
This will pass if the given input is in the searched string.
I'm trying to convert html to bbcode.
My code:
var html = "<font color=\"Green\"><font size=\"4\">test</font></font>"
html = html.replace(/\<font color="(.*?)"\>(.*?)\<\/font\>/ig, "[color=$1]$2[/color]");
Result:
[color=Green]<font size="4">test[/color]</font>
But I need to get another
[color=Green]<font size="4">test</font>[/color]
Please could you correct my mistake. Sorry for my English.
You're going to have difficulty parsing html with regex as you can see from the many many posts on this site about it. Html is not a regular language, and it therefore can be impossible to parse in this way. That being said, if the problem is this simple it should be possible.
Here's a solution that will work in very simple cases to get the first and last part
var html = "<font color=\"Green\"><font size=\"4\">test</font></font>"
,findTag = /<.*?>|([^<]+)/g
,part
,allParts = []
;
while((part = findTag.exec(html)) !== null) {
allParts.push(part[0]);
}
console.log(allParts)
var first = allParts[0]
,last = allParts.slice(-1)[0]
;
console.log(first, last);
You can then parse the first and last as you were doing previously and use array.join() to join everything back.
But again, this will only work in the simple case.
Use negative lookaheads:
html = html.replace(/\<font color="(.*?)"\>(.*?)\<\/font\>(?!\<\/font\>)/ig, "[color=$1]$2[/color]");
To explain what's happening here: The pattern I used is exactly yours, except for an appended (?!\<\/font\>). This so-called negative lookahead basically says: "only make this a match, if I don't encounter </font> next".
Basically I was playing around with an Steam bot for some time ago, and made it auto-reply when you said things in an array, I.E an 'hello-triggers' array, which would contain things like "hi", "hello" and such. I made so whenever it received an message, it would check for matches using indexOf() and everything worked fine, until I noticed it would notice 'hiasodkaso', or like, 'hidemyass' as an "hi" trigger.
So it would match anything that contained the word even if it was in the middle of a word.
How would I go about making indexOf only notice it if it's the exact word, and not something else in the same word?
I do not have the script that I use but I will make an example that is pretty much like it:
var hiTriggers = ['hi', 'hello', 'yo'];
// here goes the receiving message function and what not, then:
for(var i = 0; i < hiTriggers.length; i++) {
if(message.indexOf(hiTriggers[i]) >= 0) {
bot.sendMessage(SteamID, randomHelloMsg[Math stuff here blabla]); // randomHelloMsg is already defined
}
}
Regex wouldn't be used for this, right? As it is to be used for expressions or whatever. (my English isn't awesome, ikr)
Thanks in advance. If I wasn't clear enough on something, please let me know and I'll edit/formulate it in another way! :)
You can extend prototype:
String.prototype.regexIndexOf = function(regex, startpos) {
var indexOf = this.substring(startpos || 0).search(regex);
return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf;
}
and do:
var foo = "hia hi hello";
foo.regexIndexOf(/hi\b/);
Or if you don't want to extend the string object:
foo.substr(i).search(/hi\b/);
both examples where taken from the top answers of Is there a version of JavaScript's String.indexOf() that allows for regular expressions?
Regex wouldn't be used for this, right? As it is to be used for expressions or whatever. (my > English isn't awesome, ikr)
Actually, regex is for any old pattern matching. It's absolutely useful for this.
fmsf's answer should work for what you're trying to do, however, in general extending native objects prototypes is frowned upon afik. You can easily break libraries by doing so. I'd avoid it when possible. In this case you could use his regexIndexOf function by itself or in concert with something like:
//takes a word and searches for it using regexIndexOf
function regexIndexWord(word){
return regexIndexOf("/"+word+"\b/");
}
Which would let you search based on your array of words without having to add the special symbols to each one.
I'm trying to do something very simple, but I can't get to work the way I intend. I'm sure it's doing exactly what I'm asking it to do, but I'm failing to understand the syntax.
Part 1:
In the following example, I want to extract the part of the string between geotech and Input.
x = "geotechCITYInput"
x.match(/^geotech(.*)(?:Input|List)$/)
The result:
["geotechCITYInput", "CITY"]
I've been writing regex for many years in perl/python and even javascript, but I've never seen the ?: syntax, which, I think, is what I'm supposed to use here.
Part 2:
The higher level problem I'm trying to solve is more complicated. I have a form with many elements defined as either geotechXXXXInput or geotechXXXXList. I want to create an array of XXXX values, but only if the name ends with Input.
Example form definition:
obj0.name = "geotechCITYInput"
obj1.name = "geotechCITYList"
obj2.name = "geotechSTATEInput"
obj3.name = "geotechSTATEList"
I ultimately want an array like this:
["CITY","STATE"]
I can iterate over the form objects easily with an API call, but I can't figure out how to write the regex to match the ones I want. This is what I have right now, but it doesn't work.
geotechForm.forEachItem(function(name) {
if(name.match(/Input$/)
inputFieldNames.push( name.match(/^geotech(.*)Input$/) );
});
Any suggestions would be greatly appreciated.
You were missing the Input and List suffix in your regex. This will match if the name starts with geotech and ends with either Input or List and it will return an array with the text in the middle as the second item in the array.
geotechForm.forEachItem(function (name) {
var match = name.match(/^geotech(.*)(Input|List)$/);
if (match) {
inputFieldNames.push(match[1]);
}
});
Considering features like EditArea's and CodeMirror's autocomplete, I was wondering if, like Dreamweaver, there is a way to detect if the last word you entered is in a certain list then provide the same kind of suggestion box but with the function's arguments. I imagine you would use a regular expression on the entire field or possibly split() the whole thing (or the current line) then use the length attribute of the array to find the last bit of text, then do something involving an indexOf-like operation; however, this seems like it would get a bit resource-intensive. It almost looks like I've answered my own question, but it always helps to fully explain one's quandary, especially publicly. There's gotta be a better solution than mine. I appreciate any input. Thank you.
Put the list of words to match in an object, have the text or options to display as the value. Then on keyup or keypress you can get the last word of the text area using a function like:
function showLastWord(id){
var el = document.getElementById(id);
var lastWord = el.value.match(/\w+$/);
return lastWord? lastWord[0] : '';
}
Then check if the word is in the list and do stuff appropriately.
Edit
A small example is:
<textarea onkeyup="showHelp(this);"></textarea>
<script>
var getLastWord = (function() {
re = /\w+$/;
return function (s){
var lastWord = s.match(re);
return lastWord? lastWord[0] : '';
}
}());
var keyWords = {foo:'foo was typed',bar:'bar was typed'};
function showHelp(el) {
var lastWord = getLastWord(el.value);
// Check for matching own property of keyWords
if (keyWords.hasOwnProperty(lastWord)) {
// Do stuff
console.log(keyWords[lastWord]);
}
}