First If statement works just fine, then it goes into the for loop as expected BUT THEN OUT OF NOWHERE, it decides to execute both if statements (which they are contradictory of each other "==" and "!=")..I don't understand :(
if($scope.firstinitial==$scope.firstinput&&$scope.secondinitial==$scope.secondinput){
$scope.initialmatches="MATCHES THE INITIALS";
for (var i=0; i<$scope.discountcodes.length; i++) {
console.log($scope.discountcodes[i]);
if($rootScope.discountcodeinput.attempt.toLowerCase()!=$scope.discountcodes[i]){
$scope.changeBack();//DOES ONLY IF INPUT DOES NOT MATCH DATA
}
if($rootScope.discountcodeinput.attempt.toLowerCase()==$scope.discountcodes[i]){
console.log($scope.discountcodes[i]);//DOES ONLY IF INPUT MATCHES DATA
$scope.changeBackAgain();
}
}
}
UPDATE:
After bug testing, only the last discount code when matched works correctly...which boggles my mind even further. So when the user types in the discount code which matches the last discount code in the array, then only the first if statement triggers and not the second one. Any ideas?
I think whatever is happening inside $scope.changeBack(); is making the second condition true
If $scope.changeBack(); does something to modify discountcodes[i] or $rootScope.discountcodeinput.attempt it is possible for the second if statement to execute. What you probably mean to do is:
for (var i=0; i<$scope.discountcodes.length; i++) {
if($rootScope.discountcodeinput.attempt.toLowerCase()!=$scope.discountcodes[i]){
$scope.changeBack();//DOES ONLY IF INPUT DOES NOT MATCH DATA
}
else {
$scope.changeBackAgain();
}
}
Apparently using the == operator can have very unexpected results due to the type-coercion internally, so using === is always the recommended
also add an else statement in there if you don't need both of them executing.
Other than that I would say that something is changing, I would step through it in the debug window and see what the current results are for each variable or print them to the console.
if($scope.firstinitial==$scope.firstinput&&$scope.secondinitial==$scope.secondinput){
$scope.initialmatches="MATCHES THE INITIALS";
for (var i=0; i<$scope.discountcodes.length; i++) {
console.log($scope.discountcodes[i]);
if($rootScope.discountcodeinput.attempt.toLowerCase()!==$scope.discountcodes[i]){
$scope.changeBack();//DOES ONLY IF INPUT DOES NOT MATCH DATA
}
else if($rootScope.discountcodeinput.attempt.toLowerCase()===$scope.discountcodes[i]){
console.log($scope.discountcodes[i]);//DOES ONLY IF INPUT MATCHES DATA
$scope.changeBackAgain();
}
}
}
Trying using the else if statement to run one code then the other
<script>
if($scope.firstinitial==$scope.firstinput&&$scope.secondinitial==$scope.secondinput){
$scope.initialmatches="MATCHES THE INITIALS";
for (var i=0; i<$scope.discountcodes.length; i++) {
console.log($scope.discountcodes[i]);
if($rootScope.discountcodeinput.attempt.toLowerCase()==$scope.discountcodes[i]){
console.log($scope.discountcodes[i]);//DOES ONLY IF INPUT MATCHES DATA
$scope.changeBackAgain();
} else if($rootScope.discountcodeinput.attempt.toLowerCase()!=$scope.discountcodes[i]){
$scope.changeBack();
}
}
}
</script>
Obviously ($rootScope.discountcodeinput.attempt.toLowerCase()!=$scope.discountcodes[i] and ($rootScope.discountcodeinput.attempt.toLowerCase()==$scope.discountcodes[i] can not be true at the same time. So I guess you are doing some magic inside $scope.changeBack() that changes the value of either $rootScope.discountcodeinput.attempt or $scope.discountcodes[i], so when the second if gets checked, the value has already changed and the condition passes.
I would suggest breaking out of the iteration as soon as you know you are done, by adding a continue statement. Something like this:
for (var i = 0; i < $scope.discountcodes.length; i++) {
console.log($scope.discountcodes[i]);
if ($rootScope.discountcodeinput.attempt.toLowerCase() != $scope.discountcodes[i]) {
$scope.changeBack(); //DOES ONLY IF INPUT DOES NOT MATCH DATA
continue; // done
}
// no need to check again
console.log($scope.discountcodes[i]); //DOES ONLY IF INPUT MATCHES DATA
$scope.changeBackAgain();
}
I figured it out...
Essentially the for loop was going through and checking both if statements with each object, if the first object matched it would trigger the first if statement and not the second. BUT then the for loop would continue and look at the next object in the array and only trigger the second if statement...then it would loop through with the third object in the array and again only trigger the second if statement...so on and so on.
The workaround I came up with was just embedding both into another if statement that checked for a var value of yes
if($scope.value=="no")
then I placed the not equal if statement (!=) first and the equal if statement (==) second. Finally, I added in the (==) if statement:
$scope.value="yes";
thus avoiding going through the parent if statement on every loop of the for loop.
Thanks everyone for the help...this was killing me!
Related
I'm trying to search through an array and that I've already made up. For reference:
var words = [
"low tide",
"kayak",
"coral",
"boat",
"beachball",
"hermit crab",
"sunscreen"
];
//and then ive generated an underscore already to show up on the screen `
function generateUnderscore() {
for (let i = 0; i < chosenWord.length; i++) {
underScore.push("_");
}
return underScore;
}
Now I'm trying to document the keycode that's pressed using console.log() so that I may keep track of my mistakes. However this code isn't working for some reason.
document.addEventListener("keyup", function() {
let keyword = String.fromCharCode(event.keyCode);
if (chosenWord.indexOf(keyword) > -1) {
rightWordArray.push(keyword);
console.log(rightWordArray);
}
});
Every time I use console.log or if I write an else statement into another array it only logs the keycodes into the wrongLetterArray.
i've figured it out. so if i console log any of the characters it ends up being uppercase. Edna was right in the answer however it shouldn't be .toLocaleLowerCase it should be toLowerCase for some reason everytime i logged a key in console it was uppercase. No Caps Lock wasn't on. i'm not sure if it has something to do with a built in uppercase in javascript or what. but it worked. so ship it.
If you console.log the keyword inside of your event listener, you should be able to get the key pressed. The reason why your if statement is not working is because the indexOf method is for arrays and the chosenWord I'm assuming is a string, if you're not using it on an array, it is going to return -1.
A better method to use would be charAt, which is for strings, so you can change your if statement to
if (chosenWord.charAt(keyword.toLocaleLowerCase)) {
rightWordArray.push(keyword);
console.log(rightWordArray);
}
and it should run.
This is my code:
var counter = 0;
function showAddButton() {
var cnt = document.getElementsByClassName('img-cntnr').length;
counter++; // for detecting double excecution in debugger
if (cnt < 4) {
$('#div-add').show();
} else {
$('#div-add').hide();
}
}
//someweher in my code
showAddButton();
when I call function in my code, JavaScript executes both $('#div-add').show(); and $('#div-add').hide(); lines.
I've defined a variable (counter) and watched that in debugger for detecting parallel twice call. but there is not any parallel execution and in first call if-statement executes both blocks!
how can I fix that?
Thank You.
Your issue is most likely your if statement is not the logic you want perhaps your < should be a >, because even if you were hitting it multiple times that shouldn't really effect the results of the problem because the only way for the else to hit would be if you count was actually greater than what you expected.
So either something else is hiding the div, something is modifying the class count, or your logic is not what you expected it to be.
However you can try this line of code which will get rid of all the excess logic you have
$('#div-add').toggle($('.img-cntnr').length < 4)
you can use a boolean in the toggle fuction to set the display
you can see the toggle documentation here
Here look at this jsFiddle
I cannot see any duplicate calls, nor that both blocks of if/else are executed in one call.
showAddButton always shows element because it depends on:
document.getElementsByClassName('img-cntnr').length;
which gets length of how many elements matched img-cntnr class. So, unless you are adding elements with that class to the DOM, that count will always be the same.
If you can show us jsFiddle that prints both show and hide we will have something to go by.
There is definitely something else that is causing the code to run again. What I would do is add a killer to your js and modify the else statement to look like this:
var counter = 0;
var killer = false;
function showAddButton() {
var cnt = document.getElementsByClassName('img-cntnr').length;
counter++; // for detecting double excecution in debugger
if (cnt < 4) {
$('#div-add').show();
killer = true
} else if(killer === false) {
$('#div-add').hide();
}
}
//someweher in my code
showAddButton();
I am admittedly a super newbie to programming in general. I am trying to design a quick piece of javascript to inject on a website for a class that will both uncheck and simulate a click on a series of checkboxes. This is nothing malicious, the web form we use to download data for use in this class presents way more variables than necessary, and it would be a lot more convenient if we could 'uncheck' all and only check the ones we want. However, simply unchecking the boxes via javascript injection doesn't yield the desired result. A mouse click must be simulated on each box. I have been trying to use the .click() function to no avail. Any help is greatly appreciated. My code below fails with an error of:
"TypeError: Cannot read property 'click' of null"
CODE:
var getInputs = document.getElementsByTagName("input");
for (var i = 0, max = getInputs.length; i < max; i++){
if (getInputs[i].type === 'checkbox')
getInputs[i].checked = false;
document.getElementById('shr_SUBJECT=VC' + i).click();
}
--------EDIT#1--------------
FYI, this is the website that I am trying to use this on:
http://factfinder2.census.gov/faces/nav/jsf/pages/searchresults.xhtml
if you search for and open up any of these tables they are huge. It would be awesome if I could easily pare down the variables by 'unchecking' and 'clicking' them all at once via javascript.
The code at the bottom ALMOST works.
The problem I am running into now is that it throws an error after the first or second run through the for loop:
"TypeError: document.getElementById(...) is null"
I understand that this is because the value it's trying to find doesn't exist? Sometimes on these tables the checkboxes are greyed out/don't exist or are otherwise 'unclickable'. My theory as to why I am getting this error is because in the table/form the 'available' ID's will start around:
shr_SUBJECT=VC03 or sh_SUBJECT=VC04
and it may then skip to:
shr_SUBJECT=VC06 then skip to shr_SUBJECT=VC09 and so on...
So if the for loop hits an ID that isn't available such as 05 or 07, it returns a null error :(
I did some reading and learned that javascript is able to 'catch' errors that are 'thrown' at it? My question now is that I'm wondering if there is an easy way to simply iterate to the next ID in line if this error is thrown.
Again, any and all help is appreciated, you guys are awesome.
OLD DRAFT OF SCRIPT
var getInputs = document.getElementsByTagName("input");
for (var i = 3, max = getInputs.length; i < max; i++){
if (getInputs[i].type === 'checkbox' && i < 10){
var count = i;
var endid = count.toString();
var begid = "shr_SUBJECT=VC0";
var fullid = begid.concat(endid);
document.getElementById(fullid).click();
}
else if(getInputs[i].type === 'checkbox' && i >= 10){
var count = i ;
var endid = count.toString();
var begid = "shr_SUBJECT=VC";
var fullid = begid.concat(endid);
document.getElementById(fullid).click();
}
}
--------EDIT#2----------
An example of a table that I am trying to manipulate can be found at this URL:
http://factfinder2.census.gov/faces/tableservices/jsf/pages/productview.xhtml?pid=ACS_12_5YR_DP02&prodType=table#
If you click on the 'Modify Table' button, you are able to select/deselect specific variables via the checkboxes. If you right-click on a couple of 'active' checkboxes and inspect the elements, and it looks something like this:
<input id="shr_SUBJECT=VC03" checked="" alt="hide SUBJECT=VC03" name="" value="" onclick="javascript:hiderow('SUBJECT=VC03');" type="checkbox">
<input id="shr_SUBJECT=VC25" checked="" alt="hide SUBJECT=VC25" name="" value="" onclick="javascript:hiderow('SUBJECT=VC25');" type="checkbox">
Thank you so much #Jonathan Steinbeck for the tip about the ternary operator, it really cleaned up my code.
The script works properly, but the problem I am running into now is that it doesn't iterate enough times after the try, catch statement. If there is a gap in the id #'s; say it jumps from shr_SUBJECT=VC19 to shr_SUBJECT=VC=24 the script will stop running. Is there a way to make it keep retrying the try/catch until it gets a valid ID # or one that exists/is an active checkbox?
CURRENT DRAFT OF SCRIPT :
var getInputs = document.getElementsByTagName("input");
for (var i = 3, max = getInputs.length; i < max; i += 1) {
try {
if (getInputs[i].type === 'checkbox'){
document.getElementById("shr_SUBJECT=VC" + (i < 10 ? "0" : "") + i).click();
}
}
catch (err) {
i+=1;
if (getInputs[i].type === 'checkbox'){
if (getInputs[i].type === 'checkbox'){
document.getElementById("shr_SUBJECT=VC" + (i < 10 ? "0" : "") + i).click();
}
}
}
}
When you call document.getElementById() with a non-existing ID, null is returned. Therefore this error means that you're trying to call the .click() method on null, which can't work.
So you should check what the correct ID naming scheme for the elements you want is. Maybe the elements' count starts with 1 instead of 0?
Also, the .click() doesn't work for all elements like you would expect as far as I know. So depending on the kind of element you are trying to retrieve you might have to create and dispatch your own event as suggested by RobG's comment.
EDIT in response to your recent edit:
You can wrap code that throws errors in a try-catch like this:
for (var i = 3, max = getInputs.length; i < max; i += 1) {
try {
document.getElementById("the_ID").click();
}
catch (error) {
console.error(error);
// continue stops the current execution of the loop body and continues
// with the next iteration step
continue;
}
// any code here will only be executed if there's not been an error thrown
// in the try block because of the continue in the catch block
}
Also, what are you doing with the 'i' variable? It doesn't make sense to assign it to so many variables. This does the same:
document.getElementById("shr_SUBJECT=VC" + (i < 10 ? "0" : "") + i).click();
The ... ? ... : ... is an operator (called the 'ternary operator') that works like this: evaluate the expression before the "?" - if it results in a truthy value, the expression between "?" and ":" is evaluated and becomes the result of using the operator; if the condition results to false, the part after the ":" is evaluated as the value of the operator instead. So while "if" is a statement in JavaScript (and statements usually don't result in a value), the ternary operator can be used as an expression because it results in a value.
By concatenating a string with something else, you are forcing the 'something else' to be converted to string. So an expression like this will usually result in a string:
"" + someNonStringVar
Also, it doesn't make sense to define variables in a loop body in JavaScript. JavaScript variables have function scope, not block scope. What this means is that any variables defined in the loop body exist inside the whole function as well. Therefore it is recommended to write all of the "var"s at the top of your function to make it clear what their scope is. This behaviour of JavaScript is called 'hoisting', by the way.
I've furthermore taken a look at the URL you've given in your recent edit but I fail to find the kind of naming scheme for IDs you describe. In which table did you find those?
Edit in response to your second edit:
You shouldn't mess with the 'i' variable inside the body of a for loop. It makes your code much harder to reason about and is probably not what you want to do anyway. You don't need to handle the next step of the iteration in the catch block. The 'i' variable is incremented even if there's an error during fetching the element from the DOM. That's why you use catch in the first place.
I have the following JS code, I feel weird that only the first for loop can run, but the 2nd part doesn't work. I even tried to make two different if statement and include the for loop separately, but the same thing happened. If I run the for loop separately (by deleting another for loop), both of them can run, means both of the logic should be correct. Please help.
var s = "<?php printf($resultDataOrderInfo[0][status]); ?>";
if(s == "Processing"){
var t = document.getElementsByTagName("input");
for (i=0; i<=t.length; i++){
t[i].setAttribute("readonly","true");
} // only this above part can run
var d = document.getElementsByName("delete");
for (i=0; i<=d.length; i++){
d[i].setAttribute("hidden","true");
}
}
I think you want to change all of the <= to <. If length is equal to 0, then it is going to execute once, but fail due to the length being zero. Which, I believe is the issue of it not reaching the second for loop, due to an error occurring on the first.
Ladies and gentlemen,
I'm stuck. I've been pondering this (and obviously have failed since I'm asking for your valuable assistance) in trying to get my code to work.
I need to come up with a simple (...I'm sorry, i'm new to this) code that prompt users to keep entering names using a loop. If the user does not enter 'q'(without quotes) and if the value entered is NOT null, then the value entered should be added to the array (in my case, names).
If the user enters 'q', the loop should stop, 'q' will not be entered in the array and the list of names should be printed (through the second function in my code).
Here's what I have so far... I can make the code work if I tell the loop to run i<5... it runs 5 times and then it stops. But it fails if i do i < names.length..it causes it say that length is null or not an object (on line 10). That's problem one. And for the life of me, I can't figure out how to add the logic that will run the loop until user enters q.
Please help!
Thank you.
function getNames(){
var names = new Array();
for(i=0;i<names.length;i++){ /*if i do i=0;i<5;i++, the code works; it doesn't with this*/
names[i] = prompt("Enter an item to add to the Name list (enter \'q\' to quit","");
}
printNames(names);
}
function printNames(names) {
for(x=0; x < names.length;x++){
document.write(names[x] + '<br />');
}
}
getNames();
printNames();
I am sure somewhere in your class/book it talks about while loops. So you want to use a while loop if you want them to keep entering without a limit.
while (myCondition===true) {
//do something
}
Now look at your for loop and figure out why it is failing.
for(i=0;i<names.length;i++)
Look at what it is doing:
i = 0
names.length = 0
Is 0 < 0?
Well to start with Problem 1:
Your names array begins with a length property of 0 and so your first for loop doesn't run because 0 is not less than 0.
Which leads to Problem 2:
Again since nothing was entered into your names array your second for loop again does nothing and doesn't execute document.write because the length property of your array is still 0.