Executing function certain number of times - javascript

I'm new to programming so this question may be really basic but I need some help.
I have a code for generating a message a certain no. of times from input given by the user.
(ex.)
var count=document.getElementById("count").value;
for(var i=0;i<count;i++)
{
GenerateMessage();
}
function GenerateMessage()
{
\*
...*/
}
But no what matter the value of count is the function is executed only once. Am I doing something wrong?
EDIT: Works fine with breakpoints. But during program execution program generates one message irrespective of count value goven by user

It should be
document.getElementById("count").value
Value is a property, not a function.

try this //jsfiddle.net/W4Km8/286/ its useful for you

Related

Limit what javascript a user can input

I want to allow users to enter their own math formulas into a field that I can run via javascript, but I only want them to enter math related code and also let them have access to only the Math object.
So I only want the user to be able to enter math symbols (+, -, *, %, etc) and use any function in the Math object.
I initially thought about using regex on the client and server to verify that they are only typing in what i allowed, and since they wont be able to run that code before it goes to the server, i thought maybe it would be OK, but I still don't know if just regex itself would even work for this.
How can I go about safely allowing and trusting a users input like this?
Edit: The formulas will always run on the client, but I will store them in the db as a string that i can send to them when they want to run it.
So a number of comments led me to find MathJs, and from reading some of the docs and comments on that site I see it is safe to allow user input and also allows the Math object.
And combining this with workerpool to limit execution time, I think that should have everything I'm needing.
Thanks to those who helped point me in the right direction!
If you can guarantee that text will not be executed on the server then conceptually you can try evalFormula below :
<html>
<head>
<script type="text/javascript">
function evalFormula(str) {
// shielding
var window = null;
var document = null;
// shortcuts
var abs = Math.abs;
return eval(str);
}
console.log( evalFormula("abs(-42)") );
console.log( evalFormula("document.write('')") ); // throws error
</script>
</head>
<body>
</body>
</html>
Note that the function contains // shielding section that shall contain "caps" for all "dangerous" objects that shall be prohibited in formula context.
Note: that set is quite difficult to define in full but in principle possible.
Local scope of the function may contain shortcuts of Math functions, so they can be used as abs(-42) but not as Math.abs(-42).
Idea of the code above: In JS eval() gets executed in context of current function. So all its local variables are available for the text being evaluated.

Calculator Javascript/Jquery storing variables

I am a new student understanding javascript. I am currently having a difficult time understanding a simple concept on storing a variable on my calculator side project. My problem is when a operator (+,-,/,*) is clicked, I want to store the first value as a variable (first user input). Then after the user clicks on the digits again, the display screen will clear and display the second variable (or the second user input). Then if the operator button or equals button is pressed it will calculate the two variables (so var + var2). I have used a global variable for variable1, but I am having trouble assigning the second variable with the user input after clearing the item. I have a feeling there is a simple answer to this question, but I want to know what I am fundamentally doing wrong so I can start reviewing all the topics I need to do cover again. Anyways any help will be great! Thanks
'http://codepen.io/kevk87/pen/EVoEaa`
First thing, you have a syntax error in your statement that is causing jQuery to not select the right element. I have fixed that in my snippet below.
Second, you need to implement the equal operator to put all of this together. Meanwhile, to address your problem and point you in the right direction, You aren't really capturing the second element. Everytime the user clicks on an operator, you are reassigning the value that is on the screen to 'number' variable, then clearing the screen and assigning the value that is on the screen(which is clear because you just cleared it) to 'number2'.
One way to get around this is to check and see if the 'number' variable has a value, if so then you assign the next value to the 'number2' variable. Here's a snippet of code that does this.
$(".operator").on("click",function() {
if (number == null) {
number = $("#screen").html();
}
else {
number2 = $("#screen").html();
$("#screen").html("");
}
});
You forgot the # selector on the line $("screen").html("");, jQuery won't select the correct element. Also you haven't implemented the equal operator yet.
$(".operator").on("click",function() {
number = $("#screen").html();
$("screen").html("");
number2 = $("#screen").html();
});

Using loops with prompt()

I'm trying to get five inputs from the user.
I know that calling functions in a loop (like in the below code) will crash, because all of the prompt()'s are getting called at the same time.
for(var i = 0; i < 5; i++) {
prompt();
}
What solutions are there for this? I saw other snippets using a "timeout" with a set amount of time to wait between each function call, but would the code still work when the user can take as much time as they want to enter their prompt?
I know that calling functions in a loop (like in the below code) will crash, because all of the prompt()'s are getting called at the same time.
That't not the case here because prompt is a blocking function, just like alert. I.e. iteration (or rather code execution) only continues after the prompt windows was closed.
You could add all the values to an array like so:
var inputs = [];
for(var i = 0; i < 5; i++) {
inputs.push(prompt());
}
console.log(inputs);
Whether that's the best user experience is a different question...
No need for a timeout, the prompt will wait for user input (ok, cancel) before the rest of the code executes, meaning that the next prompt will come after clicking ok. The timeout is only usefull so that people do not accidentally press twice ok in a row and see the prompt appear.

Avoiding loop when at run-time parse a javascript code

I realized a javascript parser built in a web page.
A user can put a javascript code in the text-area like:
var i = 0;
i++;
var y = i * 10;
document.write(y);
that is parsed in order to generate some outputs (e.g., document.write stream, and so on).
The function parse is called when textarea change event is generated.
function parse(text) {
try {
....
eval(text);
} catch (e) {
....
return {
status : false, output : ..., ... : ...
};
}
return {
status : true, output : ...., ... : ...
};
}
Everything works well but I have problem when a user writes a loop in the text area (e.g., for(var i=0; i<10; ), while(true))
because the application goes in loop.
To avoid this problem, I would ask you all some questions/solutions for this problem:
Are there some javascript libraries or functions that allow to
eval a javascript code but are loop-free?
Can I ask to execute my parse function but in a fixed time? After such time I would generate an exception that stops the eval function.
Before to call the eval(text) I can call a checkIfThereAreLoops function that analyses the text seeking for patterns like for(var i=0; i<10; ) or while(true). Is this a good solution? Can I use a regular expression to seek these patterns?
If you are trying to see whether arbitrary code will terminate, you will be in for a rough time the Halting Problem is NP-Hard.
So you are right to think that you would either need a preventative measure on your parse function that either times out or dismisses unsafe input.
I'm not aware of a way to interrupt eval without the browser imposing a 'this script is running too long' limit, so you would want to sanitize the input and not evaluate anything with a loop: This will be tricky since you can't just search for constructs such as for, while etc and avoid recursive function calls.
This is a difficult problem to solve...
One 'hacky' solution could be to insert a unique variable declaration into the top of the entered code (hidden of course) and to increment this variable every other line from within the input code (again, hide these insertions and allow for syntax constructs becoming broken. Also insert sanity checks at each increment if unique_var > 99999 exit; (where 99999 is some limit you impose).
This should at least stop infinite loops.

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.

Categories