prompt number that scrolls with loop using if and else - javascript

I'm trying to insert a number in a prompt and scroll the screen using a for loop with if and else statements, and not success. The code behaves in way that when the loop iterates, the alert seems to pop in the process, and not as a result in the end "a pop up" saying there is no such number in the database to reach for, or the final result if there is the right number according to what was in the range(of numbers possible into entry) and without the pop up iterating, neither a pop up popping at least once when not wanted. The way I want the code to behave is, if there is no matching number then the alert should pop up. I would accept even a array in exchange of a better answer to the code I mentioned bellow, so that I am not restricted to a few tools(sort of say) and everything is welcome for the learning purpose. Though if there is a better solution but can be done with/without the tools I mentioned, I would pick the few tools(codes) I mentioned and it is what the preferable answer and just in case there is solution with it(the few codes I mentioned) or in case if not, I'm open to more tools available.
This is not even my best shot:
function off() {
var ik = prompt("type a number from 1 to 1000");
for(var i=0;i<1000;i++){
if(ik == i){
window.scrollTo(1366*i, 0);
break;
} else {
alert("");
}
}
}

Related

Properly modifying text pulled from a game and returning it

I'm really new to Javascript, kinda just learned a little earlier today and been messing around with it, but I'm running into a few issues her and there. I'd appreciate help from some people that know their way around the code.
What's the best way to search a string for multiple words? I'm not completely sure how to explain what I mean, so I'll include my current test code and try to explain. I'm making an attached script to pull text from a text based game online, converting it to lowercase, and defining variables for the use of a money system that changes the input text. Once changes are made, I'm re-inputting the modified text into the game as a return.
let money = 0;
const modifier = (text) => {
let modifiedText = text;
const lowered = text.toLowerCase();
let moneyChange = 0;
// The text passed in is either the user's input or players output to modify.
if(lowered.includes('take their money') || lowered.includes('take ' + 'money')) {
moneyChange = (Math.floor(Math.random() * 500));
if ((moneyChange) > 1) {
console.log(moneyChange);
money += moneyChange;
modifiedText = `You find ${moneyChange} Credits. You now have ${money} Credits`;
} else {
modifiedText = 'You find nothing.';
console.log(modifiedText);
}
}
console.log(modifiedText);
// You must return an object with the text property defined.
return {text: modifiedText};
}
modifier(text);
Currently, as you can see, I have to specifically type "Take their money" or "Take money" as an action before the text pulled is recognized as me taking money from someone or taking some in general. My main issue is that with how the game works, it's somewhat impossible to guess exactly how the input or output is going to come out. The way it works is that the game takes your character's action or speech that you type out, processes it via AI into it's own action or dialogue and generates procedural story to make more sense with the setting so that the player only has to type a vague idea of what's going to happen.
Here's an example:
There's a dead man on the street in front of you.
>loot him
You loot the man, digging through his pockets. You take some money from his wallet, but find nothing else.
The > is my only input and the rest is completely AI generated. My script looks through the AI result and , so I could look for every possible result, from "take his money" to "take her money" and so forth, but that's a little too much to bother with if there's an easier way. If I could have it search the result for specific words that may not be in the normal order and/or with other words in between. Like, it must contain the words "take" and "money" so that if the game says "You find some money, along with a gun. You take both", it recognizes that I'm taking the money. As well as the fact that I still need to write code for every single other time I do anything with money, such as buying things, and if I have to write every possible thing it's going to be a pain.
I know that it would be easier if this code was integrated into the game, but due to AI limitations, that kinda breaks how it works and it goes a little crazy... Any sort of help you can give me will be a help.
If you're looking for a way to search a string which includes multiple sub-phrases, you can use string.includes() in a loop like shown below:
function containsWords(string, words) {
for (let i=0, len=string.length; i<len; i++) {
if (!string.includes(words[i])) {
return false;
}
}
return true;
}
However you also mentioned
search the result for specific words that may not be in the normal order and/or with other words in between
Which immediately brings to mind regex, a text and string matching technology. You can easily find tutorials for regex online, and this live tester is nice too.
I'll quickly build a search string to match "take *** money", where any word can be *** as a quick introduction and example to regex:
/take .+ money/g
Here it matches the specific string take , then .+ matches one or more characters (the middle pronoun eg him/her), then matches money.

Javascript comparisons not working with prompts, while loop, and !==

What I'm trying to do is prompt the user repeatedly until one of the accepted answers is received. Pretty easy stuff. The while loop, however, is making this really weird and annoying. Here's what I got:
var plrchoice=prompt("Would you like to choose Bulbasaur, Charmander, or Squirtle? (Use only lowercase characters)");
while(plrchoice!=="bulbasaur"||plrchoice!=="charmander"||plrchoice!=="squirtle"){
plrchoice=prompt("Would you like to choose Bulbasaur, Charmander, or Squirtle?");
}
This should work in theory, but the result is an infinite do/while, regardless of what the user inputs. Thanks in advance :)
Those || should be &&.
If your rewrite the code like this, it may be clearer what happens:
var plrchoice = "";
while (!/^(bulbasaur|charmander|squirtle)$/i.test(plrchoice)) {
plrchoice =
prompt("Would you like to choose Bulbasaur, Charmander, or Squirtle?");
}

How do I change getElementById 2nd time around?

I am creating a multiple choice question that requires the user to click an answer (radio button). If the user clicks the check answer button before selecting an answer, he is prompted to select an answer. This works fine. However, if the user then selects a wrong answer and clicks the check answer button, the appropriate response is displayed over the previous prompt. I tried changing the getElementById for the prompt to display "", but it didn't work. Any help would be appreciated.
for (i = 0; i < len; i++) {
if (document.Questions.Q_ans[i].checked == false) {
document.getElementById("reply_b").innerHTML = "Select answer before continuing.";
}
}
if (document.getElementById('answer_b').checked || document.getElementById('answer_c').checked) {
document.getElementById("reply_a").innerHTML = incorrect;
document.getElementById("reply_b").innerHTML = "";
}
This line fails since incorrect should either be defined as a variable or it should be wrapped in quotes:
document.getElementById("reply_a").innerHTML = "incorrect"; // <-- Should be in quotes
So your script never executes the line after.
Use Jquery, replace all the "document.getElementById('yourId')" for "$('#yourid')"
and you must have initialized a var len for your loop.
js:
for (var i = 0; i < len; i++) {
if (document.Questions.Q_ans[i].checked == false) {
$("#reply_b").innerHTML = "Select answer before continuing.";
}
}
if ($('#answer_b').checked || $('#answer_c').checked) {
$("#reply_a").innerHTML = incorrect;
$("#reply_b").innerHTML = "";
}
As #brian buck said, your script doesn't get executed after the incorrect statement which should be a defined variable or wrapped in quotes (to be executed as a string). Your script silently fails and basically does nothing (at least, nothing you can see).
A few things here I would also recommend:
Make sure to use var i in your loop to avoid scope error
Your first loop check seems a bit odd to me: for every (assumed) possible answer not checked, you display the same error. It is not critical, but your script does something each time instead of once. You could have, let's say, a boolean that you toggle when you discover that an answer has been checked somewhere, and assign your error statement at the end depending on the value of this boolean. However, my "naked" JS is a bit rusty for that situation, and I am totally sure that there are better solutions to it!
As it appears you haven't been notified of the script failure, I don't think you use any debugger. If you are doing JS in a web browser, you could use the embedded consoles. Otherwise, there are plenty of tools taht could help you a lot. I remember losing my hair when starting to play with JS, because it got silent everytime it wasn't happy...

Whats happening? One day its OK, the next day its 'undefined'?

I am writing a greasemonkey script. Recently i had this same problem twice and i have no idea why is this happening.
function colli(){
.....
var oPriorityMass = bynID('massadderPriority');//my own document.getElementById() function
var aPriorities = [];
if (oPriorityMass) {
for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
var sCollNumber = oPriorityMass.childNodes[cEntry].getAttribute('coll');
if (bynID('adder' + sCollNumber + '_check').checked)
aPriorities.push(parseInt(sCollNumber));
}
}
.....
}
So the mystery of this is, one day i had oPriorityMass named as oPririoty. It was working fine, but the whole function was not yet complete and i started working on another functions for my script. These functions have no connection with each other.
Few days later i decided to go back to my function in the above example and finish it. I ran a test on it without modifying anything and got an error in the firefox's (4) javascript error console saying that oPriority.chilNodes[cEntry] is undefined. NOTE, few days back i have tested it exactly the same way and there was no such problem at all.
Ok, so, i decided to rename oPriority to oPriorityMass. Magically, problem got solved.
At first i thought, maybe there was some conflict of 2 objects, with the same name being used in different functions, which somehow continued to live even outside of function scope. My script is currently over 6000 lines big, but i did a search and found out that oPriority was not mentioned anywhere else but in this exact function.
Can somebody tell me, how and why is this happening? I mentioned same thing happened twice now and they happened in different functions, but the same problem node.childNodes[c] is undefined yet node is not null and node.childNodes.length show correct child count.
What is going on? How do i avoid such problems?
Thank you
EDIT: The error given by error console is
Error: uncaught exception: TypeError: oPriorityMass.childNodes[cEntry] is undefined
In response to Brocks comment:
GM_log(oPriorityMass.childNodes[cEntry]) returns undefined as a message. So node.childNodes[c] is the thing that is undefined in general.
My script creates a div window. Later, the above function uses elements in this div. Elements do have unique IDs and i am 100% sure the original site don't know about them.
My script has a start/stop button to run one or the other function when i need to.
I have been refreshing the page and running my script function now. I have noticed that sometimes (but not always) script will fail with the described error on the first run, however, if i run it again (without refreshing the page) it starts working.
The page has a javascript that modifies it. It changes some of it's element widths so it changes when the browser is resized. But i know it has no effect on my div as it is left unchanged when i resize browser.
EDIT2:
function bynID(sID) {
return top.document.getElementById(ns(sID));
}
function ns(sText) {
return g_sScriptName + '_' + sText;
}
ns function just adds the script name in front of the ID. I use it when creating HTML element so my elements never have the same id as the web page. So bynID() is simple function that saves some typing time when i need to get element by ID.
I have modified my colli() function to include check
if (oPriorityMass) {
if (!oPriorityMass.childNodes[0]) {
GM_log('Retrying');
setTimeout(loadPage,2000);
return;
}
for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
var sCollNumber = oPriorityMass.childNodes[cEntry].getAttribute('coll');
if (bynID('adder' + sCollNumber + '_check').checked)
aPriorities.push(parseInt(sCollNumber));
}
}
The loadPage function does 1 AJAX call, then i run few XPATH queries on it, but the actual contents are never appended/shown on the page, just kept inside document.createElement('div'), then this function calls colli(). So now, as i have modified my function, i checked the error console and saw that it may take up to 5 tries for it to start working correctly. 5 x 2seconds, thats 10 seconds. It is never 5 retries always, may vary There's got to be something else going on?
In Firefox, childNodes can include #text nodes. You should check to make sure that childNodes[cEntry] has nodeType == 1 or has a getAttribute method before trying to call it. e.g.
<div id="d0">
</div>
<div id="d1"></div>
In the above in Firefox and similar browsers (i.e. based on Gecko and WebKit based browsers like Safari), d0 has one child node, a text node, and d1 has no child nodes.
So I would do something like:
var sCollNumber, el0, el1;
if (oPriorityMass) {
for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
el0 = oPriorityMass.childNodes[cEntry];
// Make sure have an HTMLElement that will
// have a getAttribute method
if (el0.nodeType == 1) {
sCollNumber = el0.getAttribute('coll');
el1 = bynID('adder' + sCollNumber + '_check');
// Make sure el1 is not falsey before attempting to
// access properties
if (el1 && el1.checked)
// Never call parseInt on strings without a radix
// Or use some other method to convert to Number
aPriorities.push(parseInt(sCollNumber, 10));
}
}
Given that sCollNumber seems like it is a string integer (just guessing but it seems likely), you can also use:
Number(sCollNumber)
or
+sCollNumber
whichever suits and is more maintainable.
So, according to your last edit, it now works, with the delay, right?
But when I suggested the delay it was not meant to do (even more?) ajax calls while waiting!!
NOT:
if (!oPriorityMass.childNodes[0]) {
GM_log('Retrying');
setTimeout(loadPage,2000);
return;
More like:
setTimeout (colli, 2000);
So the ajax and the other stuff that loadPage does could explain the excessive delay.
The random behavior could be caused by:
return top.document.getElementById(ns(sID));
This will cause erratic behavior if any frames or iframes are present, and you do not block operation on frames. (If you do block such operation then top is redundant and unnecessary.)
GM does not operate correctly in such cases -- depending on what the script does -- often seeming to "switch" from top scope to frame scope or vice versa.
So, it's probably best to change that to:
return document.getElementById (ns (sID) );
And make sure you have:
if (window.top != window.self) //-- Don't run on frames or iframes
return;
as the top lines of code.
Beyond that, it's near impossible to see the problem, because of insufficient information.
Either boil the problem into a Complete, Self Contained, Recipe for duplicating the failure.
OR, post or link to the Complete, Unedited, Script.

Javascript events

I am completely confused here. So I am looking for a solution for the following problem:
I want to trigger some function(for now an alert box) using jQuery on an input field. Conditions are:
Input field always maintains the focus.
Input is fed from a USB device, which acts just like a keyboard input. So for 10 characters, there will be 10 keydown and keyup events.
Once input is filled with 10 characters, respective alert box should pop out.
Now the problem I am facing, how do I find out that input fed in is not equal to 10 characters, so throw an error alert box.(lets say just 5 chars came in input, how do I figure out the final count is 5, because there will be 5 keyup events)
You could show a message underneath/beside the input box instead of popping an alert box.
E.g. on every keyup event, check the string length, and if it's not 10, show that message.
If you really, really have to resort to alert box, you could do a timeout check, e.g. only perform the validation after 1000ms of key event inactivity. This could get very annoying on the user though.
You really have two problems here. One is just understanding the jQuery syntax (see the second part to my answer), and the other is - what is the best way to understand WHEN to throw up an error box.
To answer the second question first, my recommendation would be to not use an alert box to warn the user as they tend to be modal and really interrupt the flow of input. Secondly, as you said - how do you know when the person has stopped "typing." Unless you use some sort of timing mechanism (which is more trouble than it's worth), you don't. My suggestion would be to utilize a "div" within your HTML that shows there is an error UNTIL you reach 10 characters. Once that happens, you can hide the div. (And, of course, the div can be styled to look pretty in the meantime.)
So...how to do this...
Let's assuming your input field has an id of "myField." If you are using jQuery (which is in your tags), you would do something like this.
$(function() {
var keypresses = 0;
$('#myField').keyUp(function () {
keypresses++;
if(keypresses == 10) {
$('#error').hide(); // This is your div error with some error text in it.
// Do other stuff.
} else {
// Display an error.
}
});
Alternatively, if you don't want to use the keypresses variable, you can also use..
if($(this).val().length == 10) { }
The real issue is the fact that you are measuring in key press events, because not all key presses (even when the field has focus) will insert a character into field (for example returnesc). Therefore, you will need to measure the string length in order to validate the code before you start executing functions.
In actuality you don't even need jQuery to accomplish what you need, just bind the function call to a key press event, and only execute the function call if yourstring.length = 10
yourInput.onKeyPress(yourString.length = 10 && yourFunction());
Try -
$('#idofinputfield').keyUp(function () {
var length = $('#idofinputfield').val().length;
if(length <= 10){
alert("less than 10");
}else{
alert("greaterthan 10");
}
});

Categories