I'm creating a language quiz where users can write down their answers, like a translation for example. But I've noticed, when the answer requires punctuation, like a quotation mark, that some devices use a different style of punctuation and that will result in a wrong answer, because the punctuation used in the correct answer is just a bit different.
Here's the javascript I'm using to check answers:
<script>
var answers = {
q1: ["Auto's"]
};
function markAnswers(id) {
$(`#q${id}`).each(function () {
if ($.inArray(this.value, answers[this.id]) === -1) {
$(this).parent().append(`<br><span class='incorrect'>✗ Correct answer = ${answers[this.id]}</span>`);
} else {
$(this).parent().append("<br><span class='correct'>✓ Correct!</span>");
}
});
}
$("form").on("submit", function (e) {
e.preventDefault();
const id = e.target.id.replace("formId", "");
markAnswers(id);
$(`#submitId${id}`).each(function () {
this.setAttribute("disabled", true);
this.value = "Check answer";
});
});
</script>
As you can see, here I have an answer that requires a single quote ('), but apparently not all single quotes are equal.
I did find some code to replace specific punctuation and it's this: [^\w\s\']|_
But I'm not sure how to implement it and I would rather just accept the different punctuation. My only concerns are quotation marks and whitespace (as autofill on phones and tablets can create space).
Any suggestion on how to implement this is much appreciated. Thanks!
Edit:
Based on #Don't Panic's earlier versions of his code below (without .clean and .display) I want to make a few tweaks to it, but before I can, the code below always shows ✗ Correct answer = no matter if the answer is typed correctly or not. What could be wrong?
And about the tweaks. I've come to understand that Apple uses Smart Punctuation and this is a feature you can turn off. So I will ask my students to do that. Because I've tested it and without this feature toggled on, it will display a more straight/normal apostrophe and the answer will be accepted as correct. But since apostrophes and perhaps some other punctuation like a comma will be important, I want to add those to the existing line of code ^a-zA-Z\d. And I was thinking to at least ignore periods and extra spaces.
Thank you for all the help!
// Write out your answers without punctuation
var answers = {
q1: ["Autos"]
};
function markAnswers(id) {
$(`#q${id}`).each(function () {
// First, strip out any punctuation the user has entered
let userAnswer = this.value.replace(/[^a-zA-Z\d]/g,'');
// Now check if that "cleaned" value matches your answer
if ($.inArray(userAnswer, answers[this.id]) === -1) {
$(this).parent().append(`<br><span class='incorrect'>✗ Correct answer = ${answers[this.id]}</span>`);
} else {
$(this).parent().append("<br><span class='correct'>✓ Correct!</span>");
}
});
}
Take the user's input, strip out all punctuation, do the same to your answer, and compare the two. This way a user can use any punctuation they like, but it will just be stripped out and not part of the comparison.
This won't work if your questions are eg related to grammar, eg if you are testing when and where an apostrophe is correct, of course - in those cases the apostrophe is the answer!
The exact regular expression will depend on what has to be in your questions. Let's say you need all uppper- and lower-case letters and numbers:
$('button').on('click', function() {
markAnswers(1)
});
// Correct answers
var answers = {
"q1": "Auto's"
};
function markAnswers(id) {
$(`#q${id}`).each(function () {
// First, strip out any punctuation the user has entered
let userAnswer = this.value.replace(/[^a-zA-Z\d]/g,'');
// Strip any punctuation from the right answer
let correct = answers[this.id].replace(/[^a-zA-Z\d]/g,'');
// Now check if they match
if (userAnswer !== correct) {
$(this).parent().append(`<br><span class='incorrect'>✗ Correct answer = ${answers[this.id]}</span>`);
} else {
$(this).parent().append("<br><span class='correct'>✓ Correct!</span>");
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
What is the plural of <b>Auto</b>?
<input id='q1' type='text'>
<button>Check!</button>
</div>
To answer your new question - your code works fine for me.
I've added a button handler to actually run the check, but otherwise this is a copy-paste of your code.
If I type asdf, I get "✗ Correct answer = Autos", which is correct;
If I type autos, I get "✗ Correct answer = Autos", which is correct (lower case "a" instead of "A");
If I type Autos, I get "✓ Correct!", which is correct;
If I type "Auto's" (including those quotes), I get "✓ Correct!", which is correct;
$('button').on('click', function() {
markAnswers(1)
});
// Write out your answers without punctuation
var answers = {
q1: ["Autos"]
};
function markAnswers(id) {
$(`#q${id}`).each(function () {
// First, strip out any punctuation the user has entered
let userAnswer = this.value.replace(/[^a-zA-Z\d]/g,'');
// Now check if that "cleaned" value matches your answer
if ($.inArray(userAnswer, answers[this.id]) === -1) {
$(this).parent().append(`<br><span class='incorrect'>✗ Correct answer = ${answers[this.id]}</span>`);
} else {
$(this).parent().append("<br><span class='correct'>✓ Correct!</span>");
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
What is the plural of <b>Auto</b>?
<input id='q1' type='text'>
<button>Check!</button>
</div>
Related
I have a scenario where I need to run regex tests on a numeric input that represents phone company operator services.
In one instance, there is a prefix 118 which can act on its own or with a suffix of up to two digits.
At the moment, my function looks something like the below. My problem is that the least specific '118' exact match fires before the more specific one.
There is no sleep/wait in Javascript and unless I'm mistaken, I don't think I can get setTimeout to return a simple "return true" ?
I don't mind if the answer to this question is in pure Javascript or Jquery, but not having a dependency on Jquery would be preferable.
function isOperatorService(vNumber) {
var vNumber = vNumber.replace(/\D/g,'');
if (/^((44){0,1}118[0-9]{3})$/.test(vNumber)) {
console.log("118 specific");
return true;
}
if(/^((44){0,1}[19]{1}[0-9]{1}[0-79]{1})$/.test(vNumber)) {
console.log("Other shortcodes");
return true;
}
return false;
}
UPDATE: Re: "Provide your input and expected output."
Pretty much as I described above, in Pseudo-code :
if == 118
wait incase the user has not finished typing (e.g. wait incase 118118...)
else
do other regex cheks
Add a simple debouncer:
var timeout;
var typeDelay = 300; // wait after last type
var changeEvents = "propertychange keyup input paste change";
$('#yourinput').on(changeEvents, function () {
//clear your timeout
clearTimeout(timeout);
// Add another listener
timeout = setTimeout(function () {
// Do your regex here
function_ended_typing();
}, typeDelay);
});
Is it possible to check the XMLHttpRequestObject.responseText value using if condition instead of just displaying it?
I have tried like this.
var a=XMLHttpRequestObject.responseText;
if(a=="false")
{
document.getElementById("show_mark").innerHTML =a;
}
I know its wrong,but i need to do like this.Is there any other alternative way for doing this?Help me i am completely a newbie to AJAX.
It is possible that the response text has added white spaces. To remove white spaces at the start and end of a string use string.trim().
In your case a=a.trim()
If trim is not available in your browser's JavaScript interpreter add in
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, '');
};
}
Source
Finally i found the mistake.Its not the white spaces around the value.Actually its all the html tags like <html><body>false</body> etc., I removed these characters with the help of this code. I got the answer.
var a=XMLHttpRequestObject.responseText;
a = a.replace(/&(lt|gt);/g, function (strMatch, p1){
return (p1 == "lt")? "<" : ">";
});
var b = (a.replace(/<\/?[^>]+(>|$)/g, "")).trim();
if(b=="false")
{
document.getElementById("show_mark").innerHTML =b;
}
Thanks for the support.
I am very new to js/jquery (obviously) and am working on a small project that involves changing the case to toUpperCase on all letters except for "o", which will remain/change to lowercase.
I have implemented this: http://jsfiddle.net/HwTEj/
$(function() {
$('input').keyup(function() {
this.value = this.value.toUpperCase();
});
});
however I am struggling to define certain letters to remain/change to lowercase.
Any help on this would be greatly appreciated, and since I am new to posting questions to SO please let me know if there is any additional info you need to point me in the right direction.
To replace all instances you will need something like this:
this.value.toUpperCase().replace(/O/g, "o")
EDIT:
If you want to have a selection of characters that will be replaced you could do this (using o, f and h as an example here):
this.value.toUpperCase().replace(/[OFH]/g, function($1){
return $1.toLowerCase();
})
Updated fiddle
$(function() {
$('input').keyup(function() {
this.value = this.value.toUpperCase().split('O').join('o');
});
});
The other answers are good, but here's an alternative:
this.value = this.value.replace(/(o)|./ig, function(x, y) {
return y ? y.toLowerCase() : x.toUpperCase();
});
You can replace o in the pattern with a character class (e.g. [xyz]) if you need to make other characters lower case.
How can change this numeric(normal number formatting) js code as that just accept number and ,, mean don't accept word or character(like: -, =, +,!, and ...) just accept number and ,. How is it?
Example: http://jsfiddle.net/fQb9X/
$(document).delegate('input.numeric:text', 'keyup', function () {
$val = $(this).val().match(/[0-9]/g).reverse().join("").match(/[0-9]{1,3}/g).join(",").match(/./g).reverse().join("");
$(this).val($val)
});
I actually wrote something just like this recently:
var oldnumber='';
var $ctrl=$('input[name=passport_number]');
$ctrl.focusout(function () {
if (isFinite($ctrl.val()) || $ctrl.val()==',') {
oldnumber=$ctrl.val();
} else {
$ctrl.attr('value',oldnumber);
}
});
Basically, if you type in a valid answer, it remembers that value. If you write anything but a number or a ',', the field is set back to its previous valid value.
My solution is decently short and pretty darn clean if you ask me. It checks if it is a number, if not, it denies your entry.
EDIT
If you want it to happen while you type, try this:
$('input').bind('keyup change',function(){
var v = parseInt($(this).val());
$(this).val((isNaN(v) && v!=',')?'':v);
});
Hope that helps :)
I am stuck in implementing the following:
User starts typing in a textbox.
The javascript on page captures the first character typed, validates that it is an english alphabet (a-z,A-Z) and converts it to lowercase (if necessary).
Make an XMLHttp request based on the input (i.e. if first input character is a, get a.xml, if b get b.xml and so on).
I know how to do the last part (make the xmlhttp request) but am kind of stuck on how to capture the first character and validate it (in a way that works on all browsers). Please guide. Thanks.
Clarification: This is to create a Google Suggest like autocomplete-drop-down menu without the need for server side programs.
Something like this should work:
HTML:
<input type="text" id="myField" />
And in JS:
window.onload = function() {
document.getElementById('myField').onkeyup = function() {
// Validate that the first letter is A-Za-z and capture it
var letter = this.value.match(/^([A-Za-z])/);
// If a letter was found
if(letter !== null) {
// Change it to lowercase and update the value
letter = letter[0].toLowerCase();
this.value = letter + this.value.substring(1);
// Do the request
}
}
}
My vanilla-JS skills are a bit rusty but this should do the trick. Just for the heck of it, here's the same using jQuery:
$(function() {
$('#myField').keyup(function() {
var letter = $(this).val().match(/^([A-Za-z])/);
// If a letter was found
if(letter !== null) {
// Change it to lowercase and update the value
letter = letter[0].toLowerCase();
$(this).val(letter + $(this).val().substring(1);
// Do the request
}
});
});
What part of the problem do you not know how to do? Here's an approach that you can follow. Very likely to need adjustments, but a good starting point
if our text field's id is 'txt'
document.getElementByID('txt').onkeypress = function(e) {
var textInField = this.value;
if (textInField.length == 1) {
var firstChar = textInField.charAt(0);
if (/[a-zA-Z]/.test(firstChar)) {
sendXHR(textInField.value.toLowerCase())
}
} else {
// What do you do if there is one or more chars???
}
}
Note that the other answers here mention onchange, that doesn't fire until the focus leaves the field, which I don't think is what you want