Page search and textbox autofill with javascript in Tampermonkey - javascript

I am trying to write a script in Grease/Tampermonkey which will search a webpage for an question, and then fill in the textbox with the correct answer.
This is what I've come up with so far:
//There are 12 options in each array
var questions = ["fourth letter", "grass", "6x4", "NFL team", "OSU Buckeys", "35 + 15", "Yellow + Blue", "LeBron James", "Lassie", "2x9", "9x10"];
var answers = ["s", "green", "nut", 24, "Bengals", "gray", 50, "green", 23, "dog", 18, 90];
var answer = 0;
var position = 0;
var found = false;
//When the window loads, the function will trigger the While loop, which will run as long as found is false.
//The While loop triggers the For loop, which runs until the If statement has found the question.
//The For loop will run a number of times equal to the number of variables in the questions array.
//The if statement searches the webpage for each consecutive variable in the questions array until it finds a match.
//When the if statement finds a match, it notes which variable in the questions array matched, and sets found to true which should trigger the end of the while loop.
window.onload = function () {
while (found) {
for (var i = 0;i<=questions.length;i++) {
if (document.body.innerHTML.toString().indexOf(questions[i])) > -1 {
position = i;
found = true;
} else {
console.log ("No answer was found");
};
};
};
};
//Once the While loop has completed, this fills the textbox on the webpage with the answer
document.getElementById("humanverify\[input\]").innerHTML = answers[position];
Tampermonkey indicates that the code is running. However, the textbox isn't filling. I am new to Javascript, and have been piecing together bits of code and knowledge over the last week.

found is false initially hence the while loop will never executed.
try this
var questions = ["fourth letter", "grass", "6x4", "NFL team", "OSU Buckeys", "35 + 15", "Yellow + Blue", "LeBron James", "Lassie", "2x9", "9x10"];
var answers = ["s", "green", "nut", 24, "Bengals", "gray", 50, "green", 23, "dog", 18, 90];
var answer = 0;
var position = 0;
var found = false;
window.onload = function () {
for (var i = 0;i<=questions.length;i++) {
if (document.body.innerHTML.toString().indexOf(questions[i]) > -1) {
position = i;
found = true;
break;
}
}
if(found){
document.getElementById("humanverify\[input\]").innerHTML = answers[position];
}
else{
console.log ("No answer was found");
}
}

I've been fiddling with it all day, and came up with a functional result that satisfies all my needs. Here is the result:
var answers = ["s", "green", "nut", 24, "bengals", "gray", 50, "green", 23, "dog", 18, 90];
var questions = ['The fourth letter in the word "Reds" is?','What color is grass?','A buckeye is a what?',"What's 6x4?",'The NFL team in Cincinnati is called the?','The OSU Buckeys are Scarlet and?','35 + 15 is?','Yellow + Blue is?','LeBron James wears #?','Lassie was a what?','2x9 is what?',"What's 9x10?"];
var question = document.getElementsByClassName('description')[0].innerText;
var found = 0;
var answer = 0;
//browses questions variable for match to question variable, then assigns the correlating index to found, and assigns the answer to the answer variable, as pulled from the answers variable
for (var find = 0; find <= questions.length; find++) {
if (question === questions[find]) {
found = find;
answer = answers[found];
}
}
//checks the assigned radio, fills the textbox with the answer, and clicks the Vote button
var submit = function (){
document.getElementsByName('polloptionid')[3].checked = true;
document.getElementById("humanverify").value = answer;
document.getElementsByName("vote")[0].click();
}
submit();
//allows for a slight delay so that the page can load before cycling through script again
var reload = function () {
location.reload();
}
setTimeout(reload, 3000);

Related

JavaScript: Trying to subtract two variables returns NaN for me

I'm trying to build a simple calorie calculator and for some odd reason, my math for totalCalories (which is calories, an integer, minus calorieDeduction, an integer) keeps returning NaN. Can anyone tell me what I'm missing? I've tested console.log outputs on both my calories entered and on calorieDeduction and they both return as integers. I don't understand why subtracting one from the other returns NaN, unless I need to maybe define totalCalories as an integer by hand. I'm a newbie so I'm not necessarily sure the best method to do that. Any help appreciated. Thanks!
var maxCaloriesCodes = ['FMW', 'FLW', 'MMW', 'MLW'];
var maxCaloriesAllowed = [2000, 1500, 2500, 2000];
var exerciseCodes = ['FL', 'FM', 'FV', 'ML', 'MM', 'MV'];
var exerciseCalories = [240, 370, 580, 300, 460, 730];
function performAssessment(){
var genderElem = document.getElementById('gender_id');
var genderValue = genderElem.options[genderElem.selectedIndex].value;
var genderText = genderElem.options[genderElem.selectedIndex].text;
var goalElem = document.getElementById('goal_id');
var goalValue = goalElem.options[goalElem.selectedIndex].value;
var goalText = goalElem.options[goalElem.selectedIndex].text;
var exerciseElem = document.getElementById('exercise_id');
var exerciseValue = exerciseElem.options[exerciseElem.selectedIndex].value;
var exerciseText = exerciseElem.options[exerciseElem.selectedIndex].text;
var caloriesCode = genderValue + goalValue;
var caloriesAllowed;
var completeExerciseCodes = genderValue + exerciseValue;
var calorieDeduction;
var totalCalories;
// Loop through the array and locate the code to get the maximum calories
for (var codeCount = 0; codeCount < maxCaloriesCodes.length; codeCount++) {
// Determine if the current code is the array
if (maxCaloriesCodes[codeCount] == caloriesCode) {
caloriesAllowed = maxCaloriesAllowed[codeCount];
}
}
totalCalories = (calories - calorieDeduction);
// Loop through my exercise arrays and locate codes for calorie deductions
for (var codeCount = 0; codeCount < exerciseCodes.length; codeCount++){
// Determine if the current code is in the array
if (exerciseCodes[codeCount] == completeExerciseCodes) {
calorieDeduction = exerciseCalories[codeCount];
}
}
console.log(totalCalories)
}
Except for loops, if-clauses or function calls, code is executed line by line from top to bottom. In the line where you execute totalCalories = (calories - calorieDeduction), neither calories nor calorieDeduction has a value. Or actually their value is undefined, which gives you NaN.

for loop iterates strange

Good Morning,
I have a problem with for loop, I tried to make multiply progressbars on page and I try to triger them in one action:
function startProgressbaring(){
var progressArray = [
progress1 = document.querySelector('.progressbar-1'),
progress2 = document.querySelector('.progressbar-2'),
progress3 = document.querySelector('.progressbar-3'),
progress4 = document.querySelector('.progressbar-4'),
progress5 = document.querySelector('.progressbar-5'),
progress6 = document.querySelector('.progressbar-6')
];
var durationArray = [
progress1_Duration = 90,
progress2_Duration = 65,
progress3_Duration = 70,
progress4_Duration = 55,
progress5_Duration = 95,
progress6_Duration = 90
];
var id = setInterval(frame,30);
var width = 1;
function frame(){
for(var z=0; z<durationArray.length; z++){
if(width>durationArray[z]){
clearInterval(id);
console.log(durationArray[z]);
}else {
width++;
progressArray[z].style.width = width + '%';
}
}
};
Console Log with durationArray returns only 55, for example
six progressbars have values between 56 and 60 not the values from durationArray,
no idea whats going wrong, thanks for any advices
The problem is, that you do
clearInterval(id);
if one of the frames reaches its width. That automatically stops the others too. May just stop if all have ended:
function frame(){
var running=false;
for(var z=0; z<durationArray.length; z++){
if(width>durationArray[z]){
console.log(durationArray[z]);
}else {
running=true;
width++;
progressArray[z].style.width = width + '%';
}
}
if(!running) clearInterval(id);
};
I don't understand what you are trying to accomplish, but the code can be explained. You are not setting the width of your progress bars to any values in durationArray, you are setting your progress bars to the width value: progressArray[z].style.width = width + '%';. width will eventually be larger than the smallest value in the durationArray. When this happens, you stop the interval with clearInterval. width will increase a couple more times while for loop iterates for the last time.
add a single line of logging to your code and observer the output (see below).
Basicall what happens is:
your width starts with value 1, and increases with each iteration
after iterating over the 6 item array 9 times, the value of width is
54
your iteration reaches progress4_Duration with width = 58 (54 + 4)
width > durationArray[z] condition will be true, interval gets cleared, processing stops.
Assuming you only need to stop the iteration for a particular progressbar, probably you need an array of process ids and only stop the one that has sufficent width.
function startProgressbaring(){
var progressArray = [
progress1 = document.querySelector('.progressbar-1'),
progress2 = document.querySelector('.progressbar-2'),
progress3 = document.querySelector('.progressbar-3'),
progress4 = document.querySelector('.progressbar-4'),
progress5 = document.querySelector('.progressbar-5'),
progress6 = document.querySelector('.progressbar-6')
];
var durationArray = [
progress1_Duration = 90,
progress2_Duration = 65,
progress3_Duration = 70,
progress4_Duration = 55,
progress5_Duration = 95,
progress6_Duration = 90
];
var intervalArray = [];
durationArray.forEach(function(d) {
intervalArray.push(setInterval(frame,1000))
});
//var id = setInterval(frame,1000);
var width = 1;
function frame(){
for(var z=0; z<durationArray.length; z++){
// debug output
//console.log(width, durationArray[z]);
if(width>durationArray[z]){
//clearInterval(id);
clearInterval(intervalArray[z]);
console.log(durationArray[z]);
} else {
width++;
progressArray[z].style.width = width + '%';
}
}
}
}

Javascript - Array.repeat limitations?

I have an array and I'm looking to create a new array, composed of the original array contents repeated 3 times. For example:
var array = ["red", "green", "blue"];
newArray = ["red red red", "green green green", "blue blue blue"];
My code so far:
var triples = myArray.map(function(){
for (x = 0; x < myArray.length; x++){
return myArray[x].repeat(3);
};
});
console.log(triples);
But this only returns
triples = ["redredred", "redredred", "redredred"];
Any suggestions for a newbie?
You can build a simple function to do this:
var triples = function(xs) {
return xs.map(function(x) {
return [x,x,x].join(' ')
})
}
You can abstract it a bit more, as a transformation to use with map, and allow any number of repetitions:
var repeat = function(n) {
return function(x) {
return Array.apply(0, {length:n})
.map(function(){return x})
.join(' ')
}
}
['foo','bar','lol'].map(repeat(3))
//^ ['foo foo foo', 'bar bar bar', 'lol lol lol']
Here's an obnoxiously simple way of repeating all elements 3 times:
["red", "green", "blue"].map( [].join.bind(['',' ',' ','']) );
// == ["red red red", "green green green", "blue blue blue"]
this method also doesn't need "".repeat(), which is not universally supported yet.
another bonus: if a number, null, or other non-string sneaks in the array it won't break.
if you want it re-usable, that's easy enough:
var repeater = [].join.bind(['',' ',' ','']) ;
["red", "green", "blue"].map( repeater );
// == ["red red red", "green green green", "blue blue blue"]
[1,2,3,4,5].map( repeater );
// == ["1 1 1", "2 2 2", "3 3 3", "4 4 4", "5 5 5"]
There is no reason to use map and the loop. I guess you wanted either
var triples = myArray.map(function(str){
return str.repeat(3);
});
console.log(triples);
or
var triples = [];
for (var x = 0; x < myArray.length; x++) {
triples[x] = myArray[x].repeat(3);
}
console.log(triples);
However, as #digitalfresh mentioned in the comments, String::repeat doesn't insert the spaces, so you rather want to use (" "+…).repeat(3).slice(1) or use the functions presented by #dandavis or #elclanrs. Or, since you seem to use an Ecmascript 6 method anyway, you could do Array.from({length:3}, ()=>…).join(" ").

Variable scope in nested functions in Javascript

I have looked through countless examples which indicate that this is supposed to work, but it does not. I was wondering if someone could have a look and indicate why. I am trying to access the variable "dia" from within the setTimeout function, but it always returns undefined:
var dialogue = new Array();
dialogue[0] = 'Hi there Mo, I am Mark. I will be guiding through the game for you today';
dialogue[1] = 'Hey there Mark, how you doing?';
dialogue[2] = 'I am doing fine sweetie pie, how about yourself?';
dialogue[3] = 'I am good too, thanks. Are you ready for today, i.e. the big day?';
dialogue[4] = 'I certainly am, Mark';
var dcount;
var loopDelay;
var diatext;
for(dcount = 0; dcount <= dialogue.length; dcount++) {
var dia = dialogue[dcount];
if(dcount == 0) { loopDelay = 0; } else {
loopDelay = ((dia.length)*1000)/18;
}
setTimeout(function() {
alert(dia);
diatext = Crafty.e('2D, DOM, Text')
.text(dia)
.textFont({ size: '11px', weight: 'bold' })
.attr({ x: 200, y: 150, w:400, h:300})
.css();
}, loopDelay);
}
There are two problems:
The first is that the function you're passing into setTimeout has an enduring reference to the dia variable, not a copy of dia's value as of when the function was created. So when the functions run, they all see the same value for dia, which is the value it has then, after the loop is complete.
This example may help make this clearer:
var a = 1;
setTimeout(function() {
alert(a);
}, 0);
a = 2;
setTimeout(function() {
alert(a);
}, 0);
The code above shows us "2" twice. It does not show us "1" and then "2". Both functions access a as it is when they run.
If you think about it, this is exactly how global variables work. And in fact, there's a reason for that: It's exactly the way global variables work. :-)
More: Closures are not complicated
Now, sometimes, you want to get a copy of dia's value as of when the function was created. In those cases, you usually use a builder function and pass dia to it as an argument. The builder function creates a function that closes over the argument, rather than dia:
for(dcount = 0; dcount <= dialogue.length; dcount++) { // But see note below about <=
var dia = dialogue[dcount];
if(dcount == 0) { loopDelay = 0; } else {
loopDelay = ((dia.length)*1000)/18;
}
setTimeout(buildFunction(dia), loopDelay);
}
function buildFunction(d) {
return function(d) {
alert(d);
diatext = Crafty.e('2D, DOM, Text')
.text(d)
.textFont({ size: '11px', weight: 'bold' })
.attr({ x: 200, y: 150, w:400, h:300})
.css();
};
}
Because the function buildFunction returns closes over d, which doesn't change, rather than dia, which does, it gives us the value as of when it was created.
The second problem is that your loop condition is incorrect, which is why you're seeing undefined. Your loop is:
for(dcount = 0; dcount <= dialogue.length; dcount++) {
There is no element at dialogue[dialogue.length]. The last element is at dialogue[dialogue.length - 1]. You should be exiting your loop with < dialogue.length, not <= dialogue.length. With < dialogue.length, you'd still have a problem: dia would always be the last entry (see above), but at least it wouldn't be undefined.
try this
var dialogue = new Array();
dialogue[0] = 'Hi there Mo, I am Mark. I will be guiding through the game for you today';
dialogue[1] = 'Hey there Mark, how you doing?';
dialogue[2] = 'I am doing fine sweetie pie, how about yourself?';
dialogue[3] = 'I am good too, thanks. Are you ready for today, i.e. the big day?';
dialogue[4] = 'I certainly am, Mark';
var dcount;
var loopDelay;
var diatext;
for(dcount = 0; dcount < dialogue.length; dcount++) {
var dia = dialogue[dcount];
if(dcount == 0) { loopDelay = 0; } else {
loopDelay = ((dia.length)*1000)/18;
}
setTimeout(function(count) {
alert(dialogue[count]);
}, loopDelay,dcount);
}
This solution just pass an argument to the setTimeout function so it can take the array index from there and take the correct item

First Javascript program. What am I doing wrong?

I have finally gotten around to creating my first little practice program in Javascript. I know it's not elegant as it could be. I have gotten most of this code to work, but I still get an "undefined" string when I run it a few times. I don't know why. Would someone be kind enough to explain to me where this undefined is coming from?
var work = new Array();
work[1] = "product design";
work[2] = "product system design";
work[3] = "product social media post x5";
work[4] = "product Agent Recruitment system design";
work[5] = "product profile system design";
work[6] = "product Agent testing design";
work[7] = "product customer support";
work[8] = "product promotion";
var course = new Array();
course[1] = "javascript";
course[2] = "mandarin";
course[3] = "javascript practical-Code Academy";
course[4] = "javascript practical-learn Street";
course[5] = "mandarin practical-memrise";
course[6] = "new stuff with audiobooks";
var activity = new Array();
activity[1] = "listen to podcasts";
activity[2] = "chat online";
activity[3] = "Exercise";
activity[4] = "take a walk";
activity[5] = "call a friend";
var picker1 = Math.floor(Math.random()*3+1);
var picker2 = Math.floor(Math.random()*work.length+1);
var picker3 = Math.floor(Math.random()*course.length+1);
var picker4 = Math.floor(Math.random()*activity.length+1);
var group_pick = function(){
if(picker1 === 1){
return "Time to work on ";
} else if(picker1 === 2){
return "Time to learn some ";
} else if (picker1 === 3){
return "Lets relax and ";
} else {
return "error in group_pick";
}
};
var item_pick = function() {
if (picker1 === 1) {
return work[picker2] ;
} else if (picker1 === 2) {
return course [picker3] ;
} else if (picker1 === 3) {
return activity[picker4] ;
} else {
return "error in item_pick";
}
};
var task = group_pick() + item_pick();
document.write(task);
Array's start with an index of zero. When you assign a value to the 1 index, a 0 index is created you, with no value (undefined).
var arr = new Array();
arr[1] = 'hi!';
console.log(arr); // [undefined, "hi!"]
console.log(arr.length) // 2
Length is 2, check that out. You thought you had one item in that array but length is 2.
Usually it's easier to not manage the array indices yourself. And the array literal syntax is usually preferred for a number of reasons.
var arr = [];
arr.push('hi!');
console.log(arr); // ["hi!"]
console.log(arr.length) // 1
Or just create the array with the items in it directly, very handy.
var arr = [
"hi",
"there!"
];
console.log(arr); // ["hi", "there"]
console.log(arr.length) // 2
Once you are making the arrays properly, you can get a random item with simply:
var arr = ['a','b','c'];
var index = Math.floor(Math.random() * arr.length);
console.log(arr[index]); // "a", "b" or possibly "c"
This works because var index will be calculated by a random value of between 0.0 and up to but not including 1.0 times 3 (the length of the array). Which can give you a 0, 1 or a 2.
So this arr right here, has 3 items, one at 0, one at 1, and one at 2.
Learning to address arrays from zero can be mentally tricky. You sort of get used to it. Eventually.
A working example using these tips here: http://jsfiddle.net/du5Jb/
I changed how the arrays are declared, and removed the unneeded +1 from var pickerX calculations.
The problem is that the .length attribute for arrays counts the number of elements in the array starting from zero. So for example activity has elements 1 through 5, so according to Javascript the .length is actually 6. Then your random number calculation will choose a number from 1 through 7, past the end of the array. This is where the undefined comes from.
You can fix this by starting your index numbering at 0 instead of 1, so activity would have elements 0 through 4, with a .length of 5. Also remove the +1 from your choice calculations.
When you use your "pickers", you don't want to have the +1 inside of the `Math.floor functions.
Consider this array:
var array = [ "one", "two", "three" ];
array.length; // 3
The length is 3 -- makes sense, there are 3 items inside.
But arrays are zero-based.
array[0]; // "one"
array[1]; // "two"
array[2]; // "three"
array[3]; // undefined
So when you add that + 1, you're:
a) making it impossible to pick the first thing in the array
b) making it possible to pick a number that is exactly 1 higher than the last element in the array (undefined)
The problem here as i see it is that when you generate your random variables you're doing PickerX + 1...
So the right way to do it would be PickerX without the +1.
Also Off topic you shouldn't use if commands, try using switch case...
Here's the fixed code-
var work = new Array()
work[0] = "product design";
work[1] = "product system design";
work[2] = "product social media post x5";
work[3] = "product Agent Recruitment system design";
work[4] = "product profile system design";
work[5] = "product Agent testing design";
work[6] = "product customer support";
work[7] = "product promotion";
var course = new Array();
course[0] = "javascript";
course[1] = "mandarin";
course[2] = "javascript practical-Code Academy";
course[3] = "javascript practical-learn Street";
course[4] = "mandarin practical-memrise";
course[5] = "new stuff with audiobooks";
var activity = new Array();
activity[0] = "listen to podcasts";
activity[1] = "chat online";
activity[2] = "Exercise";
activity[3] = "take a walk";
activity[4] = "call a friend";
var picker1 = Math.floor(Math.random() * 3 +1 );
var picker2 = Math.floor(Math.random() * work.length );
var picker3 = Math.floor(Math.random() * course.length );
var picker4 = Math.floor(Math.random() * activity.length );
var group_pick = function(){
switch(picker1){
case 1:
return "Time to work on ";
case 2:
return "Time to learn some ";
case 3:
return "Lets relax and ";
default:
return "error in group_pick";
}
};
var item_pick = function() {
switch(picker1){
case 1:
return work[picker2] ;
case 2:
return course [picker3] ;
case 3:
return activity[picker4] ;
default:
return "error in item_pick";
}
};
var task = group_pick() + item_pick();
document.write( task );​
Don't work so hard. Zero is your friend. Let's go golfing...
var work = [
"product design", "product system design",
"product social media post x5",
"product Agent Recruitment system design",
"product profile system design",
"product Agent testing design",
"product customer support", "product promotion",
], course = [
"javascript", "mandarin",
"javascript practical-Code Academy",
"javascript practical-learn Street",
"mandarin practical-memrise", "new stuff with audiobooks",
], activity = [
"listen to podcasts", "chat online", "Exercise",
"take a walk", "call a friend",
];
function rint(cap) {
return (Math.random() * cap) | 0;
}
function pick(item) {
switch (item) {
case 0: return "Time to work on " +
work[ rint(work.length) ];
case 1: return "Time to learn some " +
course[ rint(course.length) ];
case 2: return "Lets relax and " +
activity[ rint(activity.length) ];
default: return "error";
}
}
document.write(pick(rint(3)) + '<br>');

Categories

Resources