jQuery auto correction acts weird on duplicated fields - javascript

I am using a script to auto-correct input on forms using jQuery. For example, when someone writes "abc" as his initials, the field will auto-correct the input directly to A.B.C.
These scripts work excellent. However, anyone can fill out several forms with several names. I am using knockout to duplicate the forms. So far so good, but auto-correction doesn't work on duplicated fields anymore..
The auto-correction looks like this (small part):
// 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;
});
A fiddle can be found here
Update
Thanks to raghaw Numbers now work. But other fields don't yet.

You are binding event that is not working on elements that get created in future. Here is the change I made to your code:
$(document).on("keyup", ".numbers", function(e)
// $(".numbers").keyup(function(e)
Your modified fiddle is here http://jsfiddle.net/QUxyy/9/

Related

.each() function does not loop through my object

I have the following jquery function and it seems that the .each function never loop through my object (it goes right to the "$("#AppConnect").val(appConnectString);" line without iterating).
Here's the code :
$("input").focusin(function () {
if (!$(this).hasClass("appConnectData")) {
var key, value, appConnectString = "";
$(".appConnectData").each(function (index, element) {
if ($(element).hasClass("key")) {
key = $(element).val();
} else {
value = $(element).val();
}
if (!key && !value) {
appConnectString += key + "." + value + ";";
}
});
$("#AppConnect").val(appConnectString);
}
//alert($("#AppConnect").val());
});
What I've done to find the problem with no success so far :
Check if the $(".appConnectData") is empty
Check the .each syntax (you never know :p)
Insert a breakpoint to see if I have some errors
Put the content of $(".appConnectData") in a var and then loop through the said var
Maybe it is because my .each is inside a focusin function, or maybe I did something else wrong but I can't seem to find what.
I thank you all in advance for the help provided :)
I think the problem is the if condition, you should check key && value if you want to make sure key & value has a value.
if (key && value) {
appConnectString += key + "." + value + ";";
}
Demo: Fiddle
In each case, if key exists then value will not exist and vice-versa. so the correct logical operator would be or. even this is not enough!
You can separate if to test both key and value existence:
$("input").focusin(function () {
if (!$(this).hasClass("appConnectData")) {
var key, value, appConnectString = "";
$(".appConnectData").each(function (index, element) {
if ($(element).hasClass("key")) {
key = $(element).val();
} else {
value = $(element).val();
}
if (key) {
appConnectString += key".";
}
if(value){
appConnectString +=value;
}
if(key||value){
appConnectString +=";";
}
});
$("#AppConnect").val(appConnectString);
}
//alert($("#AppConnect").val());
});

How to get the position of a typed letter in a textarea with Javascript?

I am creating a dropdown while typing in a textarea. How can I get the position of the typed letter given a keyup event?
Greg's answer seems to work. But if you want a more simpler way to get it, you can access the selectionStart property of the textarea.
For example
var myTextArea = $("#mytextarea");
myTextArea.keyup(function () {
console.log("The last typed character is at: ", myTextArea.get(0).selectionStart - 1);
});
http://jsfiddle.net/wasjdhtu/
var oldValue = '';
var keyup = function() {
var value = document.getElementById('myTextArea').value;
for(var i=0; i<value.length; i++) {
if(i >= oldValue.length) {
// letter typed at end
oldValue = value;
return; // not really necessary since we should be at the end of the loop anyway
} else if(value.charAt(i) !== oldValue.charAt(i)) {
// letter typed at i
oldValue = value;
return; // no need to keep searching
}
}
// no new letters typed
}

Filter options by reading character length inside for loop

I have a widget (the widget code in the pen linked below is not the actual code, please just pay attention to the filtering function jQuery.fn.doFilterOptions(){..}).
Use case:
I have a non-native selectbox. I need to extend its functionality to accept an onclick event which allows the user to type data into the selectbox (not targeting a traditional <select>), it should filter the .options available by simply showing or hiding them based on its inner HTML value, if no match is found at any point during the loop through the string being entered by the user, I need the options to continue not being displayed.
Issue:
Right now it works 95% of the way, the only issue is that if an invalid char is found, the loop keeps checking the rest of the users entries char by char, and if the next char is a match to any of the options in the same index, it re-display's this as a valid .option.
$('.selectbox .selected').on('keyup', function(){
var theseOptions = $(this).parent('.selectbox').find('.option');
var defaultPlaceholder = $(this).data('placeholder');
var filterOptions = (function(curSelectedVal){
if (curSelectedVal === ' ' || curSelectedVal.length === 0 || curSelectedVal === defaultPlaceholder){
theseOptions.show();
}
var optionsVal;
var doInputOptionsComparison = (function(){
var invalidOption = false;
for (var letterPos = 0; letterPos < curSelectedVal.length; letterPos++){
theseOptions.each(function(optionIteration){
var thisOption = $(this);
thisOptionsVal = thisOption.html();
if (curSelectedVal.length > thisOptionsVal.length ){ // If a longer string has been input by the user than exists in the option being iterated over, hide this option
thisOption.hide();
invalidOption = true;
}
else if ((thisOptionsVal[letterPos].toLowerCase().trim() === curSelectedVal[letterPos].toLowerCase().trim()) && invalidOption === false){ // If the input string matches this option and no invalid options have been found in the letterPos prior to it, show this option
thisOption.show();
}
else { // If the string does not match any option
invalidOptionFound = true;
thisOption.hide();
}
});
}
})();
})($(this).html());
});
Here is the demo, try selecting then typing abz you will see the filter working properly.
Now erase that input data, and now type azc. You will see the abc option comes available again because the c matches in that same index (user input[i] = optionsHtml[i] = show();), resulting the the above described undesirable effect.
http://codepen.io/nicholasabrams/pen/KwwMPG?editors=001
BONUS:
Would this be easier by using regEx to do the filtering?
I managed to use a dynamic regEx filter function it it cut the code down big time! Wow what a better solution.
$.fn.filterOptionsByUserInput = function(optionSelector){
var curInput = $(this).html().trim().replace(/ /g, '').toLowerCase();
$(optionSelector).each(function(optionIndex){
var userInputRegEx = new RegExp('^'+curInput+'.*');
if ($(this).html().toLowerCase().trim().match(userInputRegEx)){
$(this).fadeIn('slow');
}
else {
$(this).fadeOut('slow');
}
});
};
http://codepen.io/nicholasabrams/pen/LEEwrm?editors=001

jquery indexOf replacement

Here I have a hidden input field
<input type="hidden" value="php,php mysql" id="tags"/>
and I also have a normal input box which users could add their new tags, now I want to check if the new tag which user wants to add is already added for him or not, if it's already added, alert('already there');
here is my code:
var already_added = $('#tags_final').val().toLowerCase();
new_tag = new_tag.toLowerCase();
if (already_added.indexOf(new_tag) < 0){
// add it, everything is OK
}else{
alert('already there');
}
the above works just fine for normal values, for example now if i try to add "php", this is gonna alert('already there'), the problem is, if I add "mysql", this also sends the alert since it finds it in "php mysql", but "mysql" is another tag and it needs to be added. what's solutions come to mind for this?
thanks for your help
I would think you'd want to break this up into separate pieces and perform a full text comparison on the actual tag itself.
var tags = $('#tags_final').val().toLowerCase().split(',');
new_tag = new_tag.toLowerCase();
if ($.inArray(new_tag, tags) < 0) {
// add it
} else {
alert('already there');
}
var tags = $('#tags_final').val().toLowerCase().split(',');
new_tag = new_tag.toLowerCase();
if (tags.indexOf(new_tag) < 0) {
// add it
} else {
alert('already there');
}
Edit: Courtesy of #nybbler, this would be more accurate using the jquery inArray method as linked in his comment.
I think using indexOf directly on the string is faster than either a regex or splitting into an array (even more so when relying on $.inArray).
Simply wrap your already_added string of tags with commas, then do the same for the tag when searching for it with indexOf:
var already_added = ',' + $('#tags_final').val().toLowerCase() + ',';
new_tag = new_tag.toLowerCase();
if (already_added.indexOf(',' + new_tag + ',') < 0) {
// add it
} else {
alert('already there');
}
I got this idea from a similar trick used by jQuery.
Save the tags between braces [php][php mysql]
and search for it
var already_added = $('#tags_final').val().toLowerCase();
new_tag = new_tag.toLowerCase();
if (already_added.indexOf("["+new_tag+"]") < 0){
// add it, everything is OK
}else{
alert('already there');
}
You can use a function like this to look for a key in a comma separated string of keys:
function contains(keys, key) {
var i = 0, k = key.length;
for (var i = 0;(i = keys.indexOf(key, i)) != -1; i += k) {
if ((i == 0 || keys.charAt(i - 1) == ',') && (i + k == keys.length || keys.charAt(i + k) == ',')) {
return true;
}
}
return false;
}
Demo: http://jsfiddle.net/Guffa/UHH9V/

using .removeItem in localStorage

Using jQuery and localStorage, I want to keep track of how many times a player has won a game. Each time the form is submitted, the wincount or loss count goes up by one depending who won. The counter is working fine, but for some reason, the function to clear the counts is not working. I have been using that same function with removeItem() with other variable and it has been working fine.
var nicwincount;
var niclosscount;
$('#dostuff').click(function(e) {
e.preventDefault();
if (playerName === 'nic' && tempresult === win) {
nicwincount = JSON.parse(localStorage.getItem (nicwincount));
nicwincount += 1;
localStorage.setItem(nicwincount, JSON.stringify(nicwincount));
console.log(localStorage.getItem(nicwincount));
console.log(nicwincount);
}
else if (playerName === 'nic' && tempresult === loss) {
losscount = JSON.parse(localStorage.getItem(niclosscount));
losscount += 1;
localStorage.setItem (niclosscount, losscount);
console.log(localStorage.getItem(niclosscount));
}
}
I have tried using .setItem () to set the counts to 0. I have also tried using .removeItem. Haven't been able to get either of them to work for me and can't figure out why.
$('#clear').click(function(e){
e.preventDefault();
localStorage.setItem('nicwincount', 0);
localStorage.setItem('niclosscount', 0);
}
Thanks!
UPDATE:
This code works using localStorage
var nicScoreList = JSON.parse(localStorage.getItem('nicscorelist') || '[]');
var niccount = 0;
var nicTotalScore = nicScoreList.reduce(function(total, score) {
if (score === " " || total === " ") {
niccount++;
}
return +total + +score;
});
the item i am getting from localStorage is defined on a seperate page as:
scorelist = JSON.parse(localStorage.getItem(playerName + 'scorelist') || '[]');
scorelist.push(" ");
localStorage.setItem(playerName + 'scorelist', JSON.stringify(scorelist));
$('div.scorecolumn', column).html("Score: <br>" + scorelist.join('<br>'));
I know i skipped a bunch of the code it seems, so let me know if that doesnt make sense.
This code works, but the original example still isn't with nicwincount and niclosscount
You are using variables to store your items and strings to clear them.
Bareword (i.e. variable) here:
localStorage.setItem(nicwincount, JSON.stringify(nicwincount));
and string here:
localStorage.setItem('nicwincount', 0);

Categories