Autocorrection acts weird on duplicated fields - javascript

I have a form that users can duplicate, so they can submit multiple forms in one times. This works fine. However, i noticed that users don't use it the right way. For example, i ask for initials and people fill out their front name. PHP checks all fields and auto-corrects them if necessary, but this turns John into J.O.H.N.
Anyway a good way would be to autocorrectfields. This works on the initial form, but goes wrong on the duplicated forms. Especially initials acts weird. My knowledge of jQuery and Javascript is very limited, so after puzzling for weeks i still don't know how to solve it. Suggestions are welcome.
Fiddle: http://jsfiddle.net/QUxyy/15/
JS
// Lowercase
$(".lowercase").keyup(function(e)
{
$(".lowercase").val(($(".lowercase").val()).toLowerCase());
if (/[a-z]/g.test(this.value))
{
this.value = this.value.replace(/[^a-z ]/g, '');
}
});
// Initials
$(".initials").focus(function() {
var current = $(".initials").val();
$(".initials").keyup(function(e) {
var key = String.fromCharCode(e.keyCode);
if (key >= 'A' && key <= 'Z') {
current += key + ".";
this.value = current;
}
else {
current = "";
}
});
$(".initials").blur(function() {
var i = $(".initials").val();
var last = i[i.length - 1];
if (last != "." && i.length !== 0){
this.value += ".";
}
});
});
// Capitalize
$(".cap").keyup(function(e)
{
function convertToUpper() {
return arguments[0].toUpperCase();
}
val = this.value.toLowerCase().replace(/\b[a-z]/g, convertToUpper);
this.value = val;
});
Click for full code and preview

In your callback event handlers function for .voorletters use 'this', e.g:
SEE DEMO
$(document).on("keydown", ".voorletters", function(e) {
var i = $(this).val();
if (e.keyCode == 8 && i.charAt(i.length - 1) == ".") {
$(this).val(i.slice(0, -1));
current = $(this).val();
}
})
And you should do it for all your call back function as .initials, .lowercase, etc...

Related

input box asking for two specific words

I'm new to this, so I hope I can explain well enough what my problem is.
I've got a quiz and for an answer I created an input box. To get to another link you have to put two words in there but the order should not matter aka. it shouldn't matter if you write down "word1 word2" or "word2 word1", there should be only one rule: both words should be mentioned.
Is that possible?
My code so far:
function checkText()
{
var textwunf_1 = document.getElementById("wunf").value;
if(textwunf_1.toLowerCase() == "word1" && "word2"){
window.open("URL","_self");
}
else{
xxx
}
}
It does not work.
Before I only wanted to check if one word is used, like that:
var textwunf_2 = 'word1';
function checkText()
{
var textwunf_1 = document.getElementById("wunf").value;
if(textwunf_1.toLowerCase().indexOf(textwunf_2) == -1){
xxx
}
else{
window.open("URL","_self");
}
}
This worked but I can't use it for two words, because if I write
var textwunf_2 = 'word1 word2';
the order can't be 'word2 word1'...
Is there a solution to my problem?
Hopefully anyone can understand and help me, thank you!
Based on this commentary from the OP:
if the user types 3 words and two of them match with the answer, it should be also okay! even better if even 3 words or more are possible, as long as the user puts my two words in it..
You can check if both words are whitin the text using two conditions on the if:
textwunf_1.toLowerCase().indexOf("word1") >= 0
AND
textwunf_1.toLowerCase().indexOf("word2") >= 0
Try with the next code:
var textwunf_2 = 'word1';
var textwunf_3 = 'word2';
function checkText()
{
var textwunf_1 = document.getElementById("wunf").value;
if ((textwunf_1.toLowerCase().indexOf(textwunf_2) >= 0) &&
(textwunf_1.toLowerCase().indexOf(textwunf_3) >= 0))
{
window.open("URL","_self");
}
else
{
// xxx
}
}
Another approach:
var words = ["word1", "word2"];
function CheckWords() {
var inputWords = document.getElementById("wunf").value.split(' ');
var allWordsFound = true;
if (inputWords.length !== words.length) { return false; }
inputWords.forEach(function(word) {
if (words.indexOf(word.toLowerCase()) === -1) {
allWordsFound = false;
return;
}
});
return allWordsFound;
}
console.log(CheckWords());
I am creating a function that receive the text and check if include the answers(xx and yy), it doesn't matter the order. The ans list, can have 1,2 or more words, it will work.
let ans = ['xx','yy'];
function check(text){
text = text.toLowerCase();
let counter = 0;
ans.forEach((x) => {text.includes(x) && counter++ })
return counter === ans.length
}
console.log(check("aa bb")) // false
console.log(check("xx bb")) // false
console.log(check("aa yy")) // false
console.log(check("xx yy")) // true
console.log(check("yy xx")) // true

How to do something when backspace or delete is pressed

So I am having trouble getting my code to do something when I hit backspace or delete.
The code I have works just fine. It runs the following code, updating the size and value of multiple text input fields.
It calls compute(), which calls update() multiple times through updateAllFields().
function compute(input,number){
var decider = String(input.value);
updateAllFields(decider,number);
}
function update(label,convert,decider,number){
var updater = document.getElementById(label);
updater.value = parseInt(decider, number).toString(convert);
updater.style.width = ((updater.value.length + 1) * 12.5) + 'px';
}
function updateAllFields(decider,number){
update('binary',2,decider,number);
update('octal',8,decider,number);
update('decimal',10,decider,number);
update('hexadecimal',16,decider,number);
}
Now, that all runs just fine. I ran into an issue that, when an entire field is deleted, I get NaN, and can no longer edit the text fields unless I outsmart the NaN value.
How it happens is that that if a user hits "Ctrl+home", then backspace (wiping the entire field), NaN appears.
What I want, instead, is that when NaN would have appeared, all of the text inputs are reset to the same size and appearance that they were when their placeholders were showing.
I had looked this up, and found the following:
var input = document.getElementById('display');
input.onkeydown = function() {
var key = event.keyCode || event.charCode;
if( key !== 8 && key !== 46 )
return true;
};
It doesn't work. I even tried replacing the return false to instead read my replacement code:
function refresh(label,number){
var refresher = document.getElementById(label);
refresher.value = '';
refresher.size = number;
}
function refreshAllFields(){
refresh('binary','3');
refresh('octal','2');
refresh('decimal','4');
refresh('hexadecimal','8');
}
And that doesn't work.
What am I doing wrong? How can I get my fields to just reset to their original states if the entire text-field of one is wiped out?
You don't need to decrease the possibility of error. You need to prevent errors at all. Just validate the input data and you won't get NaN.
Simply add a check in your compute if the input is an integer:
function compute(input,number){
var decider = String(input.value);
if (isNumeric(decider))
{
// do something else
decider = "0"; // for example
}
updateAllFields(decider, number);
}
where isNumeric is a function which determines if a string represents number. There are many ways to do this, for example this:
function isNumeric(value)
{
if (isNaN(value)) {
return false;
}
var x = parseFloat(value);
return (x | 0) === x;
}
Also, you can stop passing your decider and number to every function as a string:
function compute(input, number){
if (isNumeric(input.value))
{
updateAllFields(parseInt(input.value, number)); // val is a Number now
} else {
updateAllFields(0); // for example
}
}
function update(label,convert,val){
var updater = document.getElementById(label);
updater.value = val.toString(convert);
updater.style.width = ((updater.value.length + 1) * 12.5) + 'px';
}
function updateAllFields(val) {
update('binary',2,val);
update('octal',8,val);
update('decimal',10,val);
update('hexadecimal',16,val);
}

Dynamic event attachment not working correctly [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
var smartActionsId = ['smartActions1','smartActions5','smartActions10'];
for (var i in smartActionsId) {
console.log("smartActionsId ="+smartActionsId[i]);
$('#' + smartActionsId[i] + ' select').change(function () {
var value = $(this).val();
var disableValue;
var ruleIndex = smartActionsId[i].substr(11);
console.log("smartActionsId ="+smartActionsId[i]+" i ="+i);
if (value === '0') {
disableValue = true;
onRuleToggle(disableValue, ruleIndex)
}
else if (value === '1') {
disableValue = false;
onRuleToggle(disableValue, ruleIndex)
}
});
}
I'm creating change event dynamically for a multiple switch slider items using the above JavaScript code. But problem I'm facing is, when I click on any switch 'i' value gets replaced with the last value i.e. in smartActionsId I have 3 elements, which ever switch I change it effects for last switch (smartActions10).
Could you please help me resolving this issue?
Other answers here fixed your problem, but I think you can refactor your code a little and make it much more understandable.
First, I don't like IDs. in your scenario, you have multiple ids which needs to be treated the same. Why not use one mighty class?
Also, ruleIndex calculated from element's ID? smells rotten.
If it tells you something about the element, it should be in an attribute or a data-* attribute.
The first bit of code fixes the markup by adding ruleIndex as data attribute and adding a .smart-actionable class. (Maybe you can even move this part to the server-side, to provide yourself with easier markup for JS).
Now, this makes the event handling quite simple.
var smartActionsId = ['smartActions1','smartActions5','smartActions10'];
for (var i in smartActionsId) {
$('#' + smartActionsId[i])
.data('ruleIndex', smartActionsId[i].substr(11))
.addClass('smart-actionable');
}
$('.smart-actionable').on('change', 'select', function() {
var value = $(this).val();
var disableValue = (value === '0');
onRuleToggle(disableValue, $(this).data('ruleIndex'));
});
Hope it will help.
You don't want to attach event listeners inside a for loop because the variable that tracks the index is used by each loop cycle. If you do that, the i variable will always equal the length of the array minus 1. Use Array.prototype.forEach() instead to prevent that.
var smartActionsId = ['smartActions1','smartActions5','smartActions10'];
smartActionsId.forEach(function (identifier, index) {
console.log("smartActionsId ="+identifier);
$('#' + smartActionsId[index] + ' select').change(function () {
var value = $(this).val();
var disableValue;
var ruleIndex = smartActionsId[index].substr(11);
console.log("smartActionsId ="+smartActionsId[index]+" index ="+index);
if (value === '0') {
disableValue = true;
onRuleToggle(disableValue, ruleIndex)
}
else if (value === '1') {
disableValue = false;
onRuleToggle(disableValue, ruleIndex)
}
});
});
Please Note: IE8 and down does NOT support Array.prototype.forEach().
You cant use for...in in this case. Please try the code below:
var smartActionsId = ['smartActions1', 'smartActions5', 'smartActions10'];
for (var i = 0; i < smartActionsId.length; i++) {
console.log("smartActionsId =" + smartActionsId[i]);
$('#' + smartActionsId[i] + ' select').change(function() {
var value = $(this).val();
var disableValue;
var ruleIndex = smartActionsId[i].substr(11);
console.log("smartActionsId =" + smartActionsId[i] + " i =" + i);
if (value === '0') {
disableValue = true;
onRuleToggle(disableValue, ruleIndex)
} else if (value === '1') {
disableValue = false;
onRuleToggle(disableValue, ruleIndex)
}
});
}
I've always use names like smartActions_1. If you can use it, then in your .change function you can use
// if 'smartActionsId' is global variable
// and if you need to get position in 'smartActionsId' array
var numInArray = $.inArray( this.parentNode.id, smartActionsId );
// this - your select DOM object
var ruleIndex = parseInt( this.parentNode.id.split( "_" )[ 1 ] );
And remember that this in .change function its select which have no id and you must use this.parentNode or $( this ).parent() to get it's holder (I think its div or somethink like that).
#Jack in comments is right: select may not be a direct child. Then you can use this code:
var parent = $( this ).closest( "[id^=smartActions]" );
var numInArray = $.inArray( parent.attr( "id" ), smartActionsId );
var ruleIndex = parseInt( parent.attr( "id" ).split( "_" )[ 1 ] );

dynamic closure functions for a game in javascript

Im working on a simple html/javascript multiplication game, in which I have a multiplication table with some inputs that represet the results of the products. in that game, you need to answer as fast as you can on as many questions as you can. to make it easy on the players, ive assign an event to the enter key to move to the next input when it is pressed.
Here is the javascript code for highlighting the rows and the enter key event:
for (var i=0; i<boardInputArray.length; i++) {
boardInputArray[i].onkeydown = (function(nextBox) {
return function(e) {
if(e.keyCode == 13) {
if(nextBox==boardInputArray.length) {boardInputArray[0].focus();boardInputArray[0].select();}
else {boardInputArray[nextBox].focus();boardInputArray[nextBox].select();}
var gameCompleted = true;
for(var c=0;c<boardInputArray.length;c++) {
if(boardInputArray[c].value == '') {gameCompleted = false;}
}
if(gameCompleted) validateGame();
}
}
})(i+1);
}
I dont want to post the entire code here, because it is very long. If you would like to see the game in action, go to:
http://www.webdesk.co.il/articles/javascript/multiplication-table-game.php
Here's the problem: I would like that each time the Enter key is pressed, it will check if the following input is empty or not. in case its not empty - skip to the next one and so on until it finds an empty input. That way, the player can go back to the question he didnt answer and not go through all the ones he did answer. makes sense?
You can probably improve this code, but it does take care of moving to the next empty box.
for (var i=0; i<boardInputArray.length; i++) {
boardInputArray[i].onkeydown = (function(currentBox) {
return function(e) {
if(e.keyCode == 13) {
var gameCompleted = true;
if(boardInputArray[currentBox].value == '')
gameCompleted = false;
for (
var c = (currentBox + 1) % boardInputArray.length;
c != currentBox;
c = (c + 1) % boardInputArray.length
)
{
if(boardInputArray[c].value == '')
{
gameCompleted = false;
boardInputArray[c].focus();
boardInputArray[c].select();
break;
}
}
if(gameCompleted) validateGame();
}
}
})(i);
}
Notes:
I've made the anonymous function a function of currentBox instead of nextBox (i instead of i + 1).
The loop goes through all the boxes except the current box, by starting at the next box, wrapping around and ending at the previous box or when it encounters a blank box.

Ways of comparing Text Content between HTML Elements

As the title says, I am looking for a way of comparing the Text content of an HTML Element with another HTML Elements's Text content and only if they are identical, alert a message. Any thoughts? Greatly appreciate it!
(Posted with code): For example, I can't equalize the remItem's content with headElms[u]'s content.
else if (obj.type == 'checkbox' && obj.checked == false) {
var subPal = document.getElementById('submissionPanel');
var remItem = obj.parentNode.parentNode.childNodes[1].textContent;
alert("You have disselected "+remItem);
for (var j=0; j < checkSum.length; j++) {
if (remItem == checkSum[j]) {
alert("System found a match: "+checkSum[j]+" and deleted it!");
checkSum.splice(j,1);
} else {
//alert("There were no matches in the search!");
}
}
alert("Next are...");
alert("This is the checkSum: "+checkSum);
alert("Worked!!!");
var headElms = subPal.getElementsByTagName('h3');
alert("We found "+headElms.length+" elements!");
for (var u=0; u < headElms.length; u++){
alert("YES!!");
if (remItem == headElms[u].textContent) {
alert("System found a matching element "+headElms[u].textContent+" and deleted it!");
}
else {
alert("NO!!");
alert("This didn't work!");
}
}
}
var a = document.getElementById('a');
var b = document.getElementById('b');
var tc_a = a ? a.textContent || a.innerText : NaN;
var tc_b = b ? b.textContent || b.innerText : NaN;
if( tc_a === tc_b )
alert( 'equal' );
Using NaN to ensure a false result if one or both elements don't exist.
If you don't like the verbosity of it, or you need to do this more than once, create a function that hides away most of the work.
function equalText(id1, id2) {
var a = document.getElementById(id1);
var b = document.getElementById(id2);
return (a ? a.textContent || a.innerText : NaN) ===
(b ? b.textContent || b.innerText : NaN);
}
Then invoke it...
if( equalText('a','b') )
alert( 'equal' );
To address your updated question, there isn't enough info to be certain of the result, but here are some potential problems...
obj.parentNode.parentNode.childNodes[1] ...may give different element in different browsers
"System found a matching element ... and deleted it!" ...if you're deleting elements, you need to account for it in your u index because when you remove it from the DOM, it will be removed from the NodeList you're iterating. So you'd need to decrement u when removing an element, or just iterate in reverse.
.textContent isn't supported in older versions of IE
Whitespace will be taken into consideration in the comparison. So if there are different leading and trailing spaces, it won't be considered a match.
If you're a jQuery user....
var a = $('#element1').text(),
b = $('#element2').text();
if (a === b) {
alert('equal!');
}
The triple equals is preferred.
To compare two specific elements the following should work:
<div id="e1">Element 1</div>
<div id="e2">Element 2</div>
$(document).ready(function(){
var $e1 = $('#e1'),
$e2 = $('#e2'),
e1text = $e1.text(),
e2text = $e2.text();
if(e1text == e2text) {
alert("The same!!!");
}
});
I will highly recommend using jQuery for this kind of comparison. jQuery is a javascript library that allows you to draw values from between HTML elements.
var x = $('tag1').text();
var y = $('tag2').text();
continue js here
if(x===y){
//do something
}
for a quick intro to jQuery...
First, download the file from jQuery.com and save it into a js file in your js folder.
Then link to the file. I do it this way:
Of course, I assume that you're not doing inline js scripting...it is always recommended too.
A simple getText function is:
var getText = (function() {
var div = document.createElement('div');
if (typeof div.textContent == 'string') {
return function(el) {
return el.textContent;
}
} else if (typeof div.innerText == 'string') {
return function(el) {
return el.innerText;
}
}
}());
To compare the content of two elements:
if (getText(a) == getText(b)) {
// the content is the same
}

Categories

Resources