I'm trying to make hangman in javascript and I want to check if the user has used a letter already. I made a var letterGuessValue = to 0 and if they add an input it = 1. I know this would say know to everything if i got it to work (it doesn't even do anything) but am I on the right track maybe? Here's my code. http://jsbin.com/aWOnAfe/5/edit
I would say add an input to a list and whenever they add another input (aka letter), check this list to see if it is already in there. If it is, then its because they've already used that letter before. If not, then it is a new letter.
I don't see where the difficult part is.
http://jsfiddle.net/DerekL/jgqQ9/
Sample code
var used = {};
$("input").keyup(function(){
var val = this.value;
alert( used[val] ? "Used" : "Not used" );
this.value = "";
used[val] = true;
});
How it works
Assign true to used.LETTER when a letter is entered. Before assigning it though, if it was undefined then it hasn't been used. If it is true then it is used.
Sometimes developers tend to use an Array to record pressed keystrokes when doing key combinations, but in this case, iterating an Array would require both more memory and computation power. A simple object is an enough fit.
Use an array to store all of the used letters and function like this to add new ones.
var inputs = []
function addLetter(letter){
var used = false;
for(var i = 0; i < inputs.length; i++){
if(inputs[i] == letter){
used = true;
break;
}
}
if(!used){
inputs.push(letter);
}
}
The easiest way is to append each letter to a string, like this:
var letters = '';
var letterPressed = 'X'; // uppercase it if appropriate for your language
if (letters.indexOf(letterPressed) > -1)
{
// you already pressed it
}
else
{
letters += letterPressed;
}
You can also use an array to store your list of presses, although IMO that's overkill.
Related
Hi I am currently using java to hide certain tabs and fields on my forms depending on the population of dropdowns, for example here is a code that is working:
//Display Transfer tab if it is a transfer application
var ctrlApplicationType = Runner.getControl(pageid, 'ApplicationType');
ctrlApplicationType.on('change', function(e)
{
if (this.getValue() == 2)
{
var tabs = pageObj.getTabs(); tabs.show(2);
}
else
{
var tabs = pageObj.getTabs(); tabs.hide(2);
}
}
);
In the example above the dropdown is fed from a lookup table and returns the primary key INT, hence ==2 works fine.
However I now have a problem when I am trying to get this to work with a checkbox, because the problem is a checkbox can have multiple options.
My lookup table for checkbox has 5 options, so if i ticked option 1, 2 and 3, the field (string) is stored as 1,2,3.
What I need to do is to do change the above code so it returns true if it contains 1, ie
if (1,2,3) contains 1 then true
if (2,3) contains 1 then false.
Any ideas would be much appreciated
Okay, against my better judgement (I'd really like to see you make your own attempt based on the information I've already given you), here you go...
var selectedString = "1,2,3"; // from your code, this is this.getValue()
var selectedArray = selectedString.split(","); // split the string into an array using a comma (,) as the split point
var foundInArray = selectedArray.includes('1'); // foundInArray is now a boolean indicating whether or not the value '1' is one of the values in the array.
if(foundInArray)
{
// do the found action
}
else
{
// do the not found action
}
If you want to compare against integer values instead of string values, that's easy enough too.
var integerArray = selectedArray.map(function(x){ return parseInt(x); });
var foundInArray = integerArray.includes(1);
Finally, all of this can be chained into a one-liner:
if(selectedString.split(",").map(function(x){return parseInt(x);}).includes(1))
{
// do found action
}
else
{
// do not found action
}
To iterate through a fixed list and show/hide each, you can do this...
var possibleTabs = [1,2,3,4,5];
for(n in possibleTabs)
{
if(selectedString.split(",").map(function(x){return parseInt(x);}).includes(n))
{
var tabs = pageObj.getTabs(); tabs.show(n);
}
else
{
var tabs = pageObj.getTabs(); tabs.hide(n);
}
}
This, of course, assumes that there is a relation between the checkbox value and the tabs. If there's not, then you're going to have to list them all out as individual if/elseif/else statements, and that is going to get out of hand really quickly.
I have an simple example here, the check boxes were already given by the framework we are using so it just checks weather it is checked or not(returns true or false). And I have three variables with different options that will be pushed in an array and gets removed when unchecked. By the way I have made it worked but I think there is more proper way to do this.
var chk1 = data.config.chk1; // returns true or false only
var chk2 = data.config.chk2; // same as above
var chk3 = data.config.chk3;
var settA = "settingsA";
var settB = "settingsB";
var settC = "settingsC";
if (chk1) {
arr.push(settA)
}
if (chk2) {
arr.push(settB)
}
if (chk3) {
arr.push(settC);
}
console.log(arr)
I would eidt your Object that contains the chk# keys (with true or false values) with the actual settings value instead. Then if its in the object you know its true. That way you can make your code easier to handle like so.
var Chks = data.config;
for(var key in Chks)
arr.push(Chks[key])
Now if your object contained data.config.chk3 = 'SettingsA' your array will contain 'SettingsA'.
Maybe this wont work for you, but as a rule of thumb if your repeating the same commands over and over you should probably abstract, like use an itterator.
I have some code here that will make validations of whether or not the input from a text box is NOT an empty string and isNaN. When i do these validations on amounts entered, i would like it to add them up.. however when a user does not enter anything in one or more amount fields the program should just add entered fields. But instead i get NaN showing in the total field.
link to full code: http://jsfiddle.net/KxNqQ/
var $ = function (id) {
return document.getElementById(id);
}
var calculateBills = function () {
var myErrorFlag = "N";
for (i = 1; i <= 4; i++) {
AmountNumber = 'amount' + i;
AmountValue = $(AmountNumber).value;
if (AmountValue != "" && isNaN(AmountValue)) {
$(AmountNumber).style.color = "red";
myErrorFlag = "Y";
} else {
$(AmountNumber).style.color = "black";
myErrorFlag = "N";
}
}
if (myErrorFlag != "Y") {
var Amount = 0;
for (i = 1; i <= 4; i++) {
Amount += parseInt($('amount' + i).value,10);
}
$('total').value = Amount;
}
}
var clearFields = function () {
for (i = 1; i <= 4; i++) {
itemName = 'item' + i;
$(itemName).value = "";
}
for (i = 1; i <= 4; i++) {
amountName = 'amount' + i;
$(amountName).value = "";
}
$('total').value = "";
}
window.onload = function () {
$("clearfields").onclick = clearFields;
$("addbills").onclick = calculateBills;
}
I think you've got your requirements a little bit confused, or at the very least I was confused by them. So in order to answer your question, I'm going to rephrase the requirements so I understand them better. This is a useful exercise that I try to do when I'm not 100% sure of the requirements; if I can't get the requirements right, what's to say I'll get the code right?
So the requirements – as I understand them – are:
Given each amount input
When the input has a value
And that value is a number
Then add the value to the total
And make the input color black
But if the input does not have a value
Or that value is not a number
Then make the input color red
Going through your code, I can see a number of problems with it. First, I noticed that both AmountNumber and AmountValue are global variables, because they were not declared local with the var keyword. So before fixing our code, let's change that. Let's also change the variable names to something that more accurately describe what they are, hopefully making the code easier to understand:
var input = $('amount' + i);
var value = input.value;
Now, note that I chose to store the element in the input variable. This is so we don't have to look it up multiple times within the loop. Looking things up in the DOM can be expensive so we'll want to keep it to a minimum. There are other was to look up elements as well, such as getElementsByClassName, querySelector and querySelectorAll; those are left as an exercise for the reader to research and evaluate.
Next, in each iteration of the loop, you check that AmountValue is not a string and simultaneously is not a number:
if (AmountValue != "" && isNaN(AmountValue)) {
This will be true so long as AmountValue is truthy (which is the case for non-empty strings) and so long as isNaN thinks it's a number (which is the case for strings that contain numbers.) It really is rather confusing; if I understand your code correctly this clause is there to check for invalid input and if it is true should mark the input field red and set a flag. I.e. this is the but clause in the aforementioned requirements.
Let's rewrite this to be the when clause instead, we'll take care of the but later. Before we do that, let's look at the myErrorFlag. It's used – I think – to see whether all input is well formed and in that case, add it all up. Well, validation and summation can be done in one fell swoop, so let's get rid of the flag and sum the values while validating them. So we replace myErrorFlag with a total variable:
var total = 0;
Now, let's get back to our clause. The requirements say:
When the input has a value
And that value is a number
Then add the value to the total
In code, that should look something like this:
if (value && !isNaN(value)) {
total += parseInt(value, 10);
input.style.color = 'black';
}
There are a couple of things going on here. For one, the if statement has been turned on its head a bit from what it was. It first checks to see that value is truthy, then that it is a number. The second check can be a bit tricky to read, because it is essentially a double negation; in english it reads "is not not a number", i.e. "is a number". I'll leave it as an exercise for the reader to figure out whether there's a more easily understood way of writing this check.
Now what about the but clause in our requirements?
But if the input does not have a value
Or that value is not a number
Then make the input color red
Well, it's essentially the inverse of our previous statement, so let's simply add an else clause:
else {
input.style.color = 'red';
}
Because the requirements doesn't mention the total variable in this clause, it is simply ignored and doesn't show up in the end result.
Adding it all up (no pun intended) the code – with comments – looks like this:
var calculateBills = function () {
var total = 0;
for (i = 1; i <= 4; i++) {
// Given each amount input
var input = $('amount' + i);
var value = input.value;
if (value && !isNaN(value)) {
// When the input has a value
// And that value is a number
// Then add the value to the total
total += parseInt(value, 10);
// And make the input color black
input.style.color = 'black';
} else {
// But if the input does not have a value
// Or that value is not a number
// Then make the input color red
input.style.color = 'red';
}
}
$('total').value = total;
};
There are more things that could be learned from this to make for better code. For instance, this code will break if the number of inputs change, or if their id names change. This is because they are selected specifically by their IDs and as such, if those change then this code will no longer function.
Another potential issue is that we're setting inline styles on the inputs as we loop over them. This means that in order to keep this code up to date with the styling of the site, it'll have to change. Generally, mixing styling and functionality like this is not a good idea and should be avoided. One way of doing so is to use class names instead, and toggle these on and off. Incidentally, this could also help the previous problem I mentioned.
There are other problems as well, but we'll leave those for another day. Hope this helps!
Try this
var calculateBills = function () {
var Amount = 0;
for (i = 1; i <= 4; i++) {
var AmountElement = $('amount' + i),
AmountValue = AmountElement.value;
if (AmountValue != "" && !isNaN(AmountValue)) {
AmountElement.style.color = "red";
Amount += parseInt(AmountValue,10);
} else {
AmountElement.style.color = "";
}
}
$('total').value = Amount;
};
Demo
Anyway, instead of using elements with id like id="amount1", id="amount2", id="amount3", etc., you could use classes (e.g class="amount") and get them with .getElementsByClassName
var tagAllowed = true;
var allowedTags =["Person","People","Dance","Word"];
if(tagAllowed === true) {
for(var i=0;i<allowedTags.length;i++){
var aTags = allowedTags[i];
if(input.val().toLowerCase() === aTags.toLowerCase()) {
tagged.append('<span unselectable="on" class="tagged '+colorize+'" title="Click To Delete">'+inputVal.trim()+'</span>');
tagSize = $('.tagged').length;
var ele = $('.tagged').last(),
subtract = parseInt(ele.outerWidth(true),10);
input.width(input.width() - subtract);
tagged.width(tagged.width() + subtract);
input.css('marginLeft','5px');
input.val("");
input.css('color','#000');
} else {
errorMess.children('span').remove();
errorMess.prepend('<span>'+errorProcess+'<span>');
errorMess.slideDown();
}
}
The following code works in a way, if the input.val() does not match it will show the custom alert errorMess and well even if the word matches it still shows the custom alert. I am wondering if maybe I am doing something wrong in my conditional. As I don't need the custom alert to appear if the words match.
If any suggestions please post. I know this isn't the best example with just a code, but I hope all of you get what I am trying to say. I just don't want the custom alert to appear if the two words match together.
You have the if-statement inside the for-loop. The input value will never equal more than one of the tags in the array. You could use a for-loop to set a boolean. Then the if-statement could follow the for-loop.
boolean isAllowedTag = false;
for(var i=0;i<allowedTags.length;i++){
var aTags = allowedTags[i];
if(input.val().toLowerCase() === aTags.toLowerCase()) {
isAllowedTag = true;
break;
}
}
if (isAllowedTag) {
// ...
} else {
errorMess.children('span').remove();
errorMess.prepend('<span>'+errorProcess+'<span>');
errorMess.slideDown();
}
}
add a break; after your input.css('color, '#000'); line. also, you should really change those last 3 lines to: input.val("").css({marginLeft:'5px', color:'#000'});. Making calls to .css() is slow, so it's better to do as much as you can in one call.
I am completely new to JavaScript.
I have size and color dropdowns on a page for users to order a product, but only certain combinations are available i.e. pink is the only color in large sizes.
I thought I'd make an array of allowed sizes and test the user input against these.
If the choice is invalid then I want a popup to tell the user why.
In the real world I'll use SQL & PHP to create the array of allowed choices, in the example below I've hard coded 3 valid choices for testing. Unfortunately the code below doesn't do anything.
I'm sure it's a simple newb mistake. I really don't know what I'm doing :)
Can somebody help me out?
The validation function is supposed to happen when user clicks the form submit...
<form id="form1" name="form1" method="post" onsubmit="return validate_form()"
action="cart.php">
Here's the function:
<script type="text/javascript">
function validate_form() {
var allowed = new Array();
allowed[0]="10,beige";
allowed[1]="10,black";
allowed[2]="10,pink";
var chosenColInd = document.getElementById("colID");
var chosenColText = colID.options[colID.selectedIndex].text;
var chosenSizeInd = document.getElementById("sizeID");
var chosenSizeText = sizeID.options[sizeID.selectedIndex].text;
var chosenSizeCol = chosenSizeText+","+chosenColText;
var found = "false";
for ( var i = 0; i < allowed.length; i++ ) {
if (allowed[i]=chosenSizeCol) {
found = "true";
}
}
if (found = "false") {
alert( 'The variation you have selected is currently unavailable. Please select another.' );
return false;
} else {
return true;
}
}
</script>
There are a few lines where you use the assignment operator (that is single equals =) instead of one of the equality operators (that is double or triple equals, triple is usually preferred in JavaScript). Example:
if (found = "false") {
Would appear to be the problem at first sight - it's an assignment not a comparison :) use triple equals === instead of single:
if(found === "false") {
Also, consider the following (commented) updates to your code, which reflects more the typical style of JavaScript code:
function validate_form() {
//no need to use new Array(), use array literal instead
var allowed = [
"10,beige",
"10,black",
"10,pink"
];
var chosenColInd = document.getElementById("colID");
var chosenColText = colID.options[colID.selectedIndex].text;
var chosenSizeInd = document.getElementById("sizeID");
var chosenSizeText = sizeID.options[sizeID.selectedIndex].text;
var chosenSizeCol = chosenColText+","+chosenSizeText;
var found = "false";
for ( var i = 0; i < allowed.length; i++ ) {
//use equality operator instead of assignment
if (allowed[i]===chosenSizeCol) {
found = true; //may as well use a boolean rather than string
break; //exit loop early, no need to continue if we've already found
}
}
if (!found) { //no need to do a comparison with already boolean values
alert( 'The variation you have selected is currently unavailable. Please select another.' );
}
//may as well just return found here now that we're using a boolean
return found;
}