In the following code, the user is able to create variables utilizing the window object via an input type text element. I've written a function that console logs the name of the variable followed by the value of 0 in which the variable is initialized. This only occurs when the following key string literal, "-nr " precedes the desired name for the created variable.
The goal of this exercise is to increment any created variable value by 1 when the variable name is reentered into the input element. My attempt at doing so is by first writing the first function, varCreate to declare and initialize variables to 0, push them into an array, and console log the variable name followed by its value. The next function which I have a problem with (varPlus) is meant to add 1 to the value of each value when a particular name is entered into the input element however, it adds a few more than 1 even when I utilize a for loop to evaluate if the string literal value of the input element value property is equivalent to each element of the array varArray.
const _in = document.getElementById('in');
var varArray = [];
function varCreate(e) {
let _key = e.key;
if(_key === "Enter") {
if(_in.value.substring(0, 4) == "-nr ") {
window[_in.value.substring(4).replace(/\s/g, "_")] = 0;
varArray.push(_in.value.substring(4).replace(/\s/g, "_"));
console.log("var: " + varArray[varArray.length - 1] + "\nvalue: " + window[varArray[varArray.length - 1]]);
_in.value = "";
}
}
}
function varPlus(e1) {
let _key1 = e1.key;
if(_key1 === "Enter") {
checker = new RegExp(_in.value.replace(/\s/g, "_"), "gi");
for(var i = 0; i < varArray.length; i++) {
if(checker.test(varArray[i])) {
window[varArray[i]] += 1;
console.log("var: " + varArray[i] + "\nvalue: " + window[varArray[i]]);
}
}
delete window["checker"];
}
}
_in.addEventListener('keydown', varCreate);
_in.addEventListener('keydown', varPlus);
<input id='in' type='text' />
The end result when attempting to utilize varPlus is that it'll console log all variable names and values which somehow increment in value when it should only be console logging only the variable name which I'm trying to access via user input followed by its value. I would greatly appreciate it if anyone can shed some light on how I'm encountering these errors.
First of all it is really helpful if you try and make your code executable :)
Now for the user generated variables you could do something like this:
// DOM Elements
const input_variable = document.getElementById("input_variable");
const button_createVariable = document.getElementById("button_createVariable");
// Variables
let userVariables = {};
// Event listeners
window.addEventListener("keyup", event => {if(event.key == "Enter") parseVariable()});
button_createVariable.addEventListener("click", parseVariable);
function parseVariable() {
// Get the variable name and remove all spaces
let variableName = input_variable.value.substring(0, input_variable.value.indexOf("=")).replace(/\s+/g, '');
// Get the variable value and remove all spaces
let variableValue = input_variable.value.substring(input_variable.value.indexOf("=") + 1, input_variable.value.length).replace(/\s+/g, '');
// Add the variable to the object
userVariables[variableName] = variableValue;
// Clear the input
input_variable.value = "";
// Log the object into the console
console.log(userVariables);
}
<input id='input_variable' type='text'/><button id="button_createVariable">Create</button>
WARNING You of course still need to verify the user input. At this state it will accept everything as input. But now you can loop through the object and count up (or whatever) if already exists.
Oh yes btw, the syntax is simply: <name> = <value> eg. foo = 10.. unimportant detail :P
Related
I'm working on a basic P5 program that requires up to ten input boxes.
So I need to first create the button instances, using e.g.
factor1Input = createInput(""); // create DOM element for input field
factor1Input.position(leftMargin, topMargin + 50); // place button on screen
factor1Input.changed(this.factor1update); // call function when value changes
factor1Button = createButton('Update Factor'); // create DOM element for button
factor1Button.position(100, 100); // position button
Then toggle their visibility using e.g.
factor1Input.show(); // toggle display on
factor1Button.show();
factor1Input.hide(); // or toggle it off
factor1Button.hide();
But because I'll have up to 10, this will require a ton of repetitive code.
So I want to create a loop that goes something like (e.g. just for the show function);
for (let i = 1; i < factorCount; i++){
let fci = "factor" + i + "Input";
let fcb = "factor" + i + "Button";
fci.show();
fcb.show();
}
But I'm getting the following error:
Uncaught TypeError: fci.show is not a function
Which suggests some kind of type mismatch, i.e. I can't seem to just compile a string, and have this recognized as the JavaScript function.
Any suggestions?
fci will be a string so the String class will not have a method show, You will get an exception. Instead
You can write in this way
var factorObject = {
factor1Input:createInput("")
}
factorObject['factor1Input'].position(leftMargin, topMargin + 50);
For show
factorObject['factor1Input'].show();
Here in the loop
for (let i = 1; i < factorCount; i++){
let fci = "factor" + i + "Input";
factorObject[fci].show();
}
The reason why your code doesn't work is because you create a string and try to call it like a variable with the same name
let fci = "factor" + i + "Input";
fci.show(); // fci is just a string 'factor1Input', has nothing in common with factor1Input variable
You should use arrays Arrays and instead of keeping input number (e.g. index) inside a name, let it be the index of an item in the array
const factorCount = 10
const inputs = []
const buttons = []
// example of creating inputs and buttons in a loop, you can create them manually if you want,
// but don't forget to .push them to respective array
for (let i = 1; i < factorCount; i++){
const input = createInput("");
input.position(leftMargin, topMargin + 50 * i); // using index to calculate top margin
input.changed((value) => this.factorUpdate(i, value)); // notice the change here
inputs.push(input)
const button = createButton('Update Factor');
button.position(100, 100 + 50 * i); // also using index to calculate top margin
buttons.push(button)
}
function showInput(index) {
inputs[index].show()
buttons[index].show()
}
function hideInput(index) {
inputs[index].hide()
buttons[index].hide()
}
showInput(3) // shows 3rd input and button
hideInput(4) // hides 4th input and button
Notice also how I changed your this.factor1update method call. The same way you don't want to have 10 separate variables for 10 elements, you don't want to have 10 methods to handle changes on those 10 elements (what if there was 10000 elements?). Instead, create one method factorUpdate that will receive item index and the value that was changed and use that to handle the input change
added:
for (let i = 0; i < factorCount; i++){ // changed 1 to 0 here, it was a typo
const input = createInput("");
input.position(leftMargin, topMargin + 50 * i);
input.changed(() => factorUpdate(i)); // we call factorUpdate with index of an element
inputs.push(input)
const button = createButton('Update Factor');
button.position(185, topMargin + 50 * i);
buttons.push(button)
}
function factorUpdate(i, event){
// argument i is now an index of unfocused input
console.log("input index: " + i + ", value: " + inputs[i].value());
}
Note also how input.changed() works: you edit the input, then you click somewhere else on the page to unfocus it, and that's when this event is triggered. With that in mind, buttons here don't actually do anything as there are no click listeners assigned to them
I have a very basic HTML, user enters something like -webkit-transition and the function returns something like WebkitTransition.
<div id='app'>Change input to camelCase</div>
<input id='getInput' />
<button id='submit' />get result</button>
<span id="output">Result: </span>
The relevant JS is this:
// initializing the input field value var let inputed = getInput.value;
// this is the function, it should take the input.value as argument
function whatComesOut (str) {
return str
.split('-')
.map(
(word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
)
.join('');
}
// updating the input value on change, this logs the correct input value
getInput.addEventListener('change', function(e){
let inputed = e.target.value;
console.log(inputed);
})
// on click I want to display the returned value from the function in the span element
submit.addEventListener('click', function(){
console.log(inputed);
output.innerHTML += whatComesOut(inputed);
})
But, nothing is happening, no errors in the console either.
A link to codepen
https://codepen.io/damPop/pen/PxYvJr?editors=0010
The question is, how do i get the return value from the whatComesOut function displayed in the span element? Do i need the pass the event object somewhere?
The issue here is that unlike in the event listener on getInput, the value of inputed is not declared in the submit event listener, so it uses the static value that was assigned on line 5. If you add const inputed = getInput.value; right before output.innerHTML += whatComesOut(inputed); this will work.
You need to make the variable inputed global instead of local to only the event listener function.
Also, change the type of your button to "button" so it does not submit the form and refresh the page.
// initializing the input field value var let inputed = getInput.value;
let inputed;
// this is the function, it should take the input.value as argument
function whatComesOut (str) {
return str.split('-').map(
(word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
).join('');
}
// updating the input value on change, this logs the correct input value
getInput.addEventListener('change', function(e){
inputed = e.target.value;
console.log(inputed);
})
// on click I want to display the returned value from the function in the span element
submit.addEventListener('click', function(){
console.log(inputed);
output.innerHTML += whatComesOut(inputed);
})
You've declared a global variable inputted And which was redeclare in one of The Event,
So this makes the initialization strict within the Event ( local scope ). The initialization to the local scope variable made no changes to the global variable.
var global = 'it's global now'
function func() { var local = 'its local variable'}
The global scope variable is accessible within the local scope and you could make changes to it since It wasn't a constant declaration.
Remove the let in line 19, erase line 26 and remove string concatenation to avoid repetition in line 28 it should work.
getInput.addEventListener('change', function(e){
inputed = e.target.value;
})
submit.addEventListener('click', function(){
output.innerHTML = camelise(inputed);
})
I'm using the code below to check if var1 exists, then assigning another variable (promt) to store var1 provided that the user types in the variable. Problem is I have about twenty variables I need to check so my code looks like the below times ten:
if (typeof var1 !== 'undefined') {
if(selection==var1){
var promt = var1;
}
}
if (typeof var2 !== 'undefined') {
if(selection==var2){
var promt = var2;
}
}
This (a) makes a ton of inefficient code and (b) may cause errors if I have over twenty variables. Is there a way to check if var1, var2, var3, etc.. exists then stop checking when the variables stop?The goal is to be able to have one hundred variables and still have the same amount of code I would have if there were two.
If your variables are fields on an object you can easily build the field names dynamically:
fieldname = 'var' + index;
if (typeof obj[fieldname] !== 'undefined') {
if (selection == obj[fieldname]){
var promt = obj[fieldname];
}
}
For local variables I however can't provide a solution.
First thing first var is reserved word in javascript, so you cannot use it as variable names, hence I use _var here instead.
I made a jsFiddle for this solution, so check it out pls.
You may also look at the code below:
for (i in _var) {
// Loop through all values in var
if ((typeof _var [i] !== undefined) &&
selection_array.indexOf(_var [i]) >= 0) {
// note that array.indexOf returns -1 if selection_array does not contain var [i]
prompt = _var[i]; // use this if you only want last var[i] satisifying the condition to be stored
prompt_array.push(_var[i]);// use this if you want to store all satisifying values of var[i]
}
}
Also check the below snippet
// Lets declare and give some example value to _var, Note that you cannot use var as variable name as it is a reserver word in javascript
var _var = ['foo1', 'foo2', 'foo3', 'foo4'];
// Declare a variable called prompt (actually not necessary normally)
var prompt;
// Declare a array called prompt_array to store the output
var prompt_array = [];
// Declare and give some example value to selection_array
var selection_array = ['foo2', 'foo3'];
// main program to solve the problem
for (i in _var) {
// Loop through all values in var
if ((typeof _var [i] !== undefined) &&
selection_array.indexOf(_var [i]) >= 0) {
// note that array.indexOf returns -1 if selection_array does not contain var [i]
prompt = _var[i]; // use this if you only want last var[i] satisifying the condition to be stored
prompt_array.push(_var[i]);// use this if you want to store all satisifying values of var[i]
}
}
// output for visualizing the result
document.getElementById('output').innerHTML += 'prompt = ' + prompt + '<br/>';
document.getElementById('output').innerHTML += 'prompt_array = ' + prompt_array.toString();
<div id="output">
</div>
You can ask me through commenting if you have a further problem on this :D.
Perhaps a slightly dim question but I'm trying to design something where I'm using javascript / jquery to change the layout of a website and I'd like to see the values of both a variable name and it's current value in another div.
I was just doing $test.append('example string' + exampleVar) a lot so I thought I would make a function called test().
So far I have:
function test (test) {
$test = $('.test');
$test.append(test+"<br>");
}
and then would pass it a variable name as an argument but I can't find any way of making it display the name as a string. I know about making it as an object to access the key and value but that doesn't really seem to work here?
Bit of a long-winded way to do it, but here's an example using an object:
function tester(options) {
var keys = Object.keys(options);
console.log(keys[0] + ': ' + options[keys[0]]); // test: My value
}
tester({ test: 'My value' });
DEMO
You could use a feature of javascript where obj["prop"] is the same as obj.prop
So instead of passing the variable as a variable and hoping to get its name, you use the name as a string to get the variable's value.
If you aren't using namespaces/variables and want to a global/root variable, pass window, eg:
function test(obj, val) {
console.log(val + ": " + obj[val]);
}
var val1 = 1;
var val2 = 2;
test(window, "val1");
test(window, "val2");
(obviously you don't get the name of 'obj' - but maybe it's a start)
if you only have root/global variables (as in the example provided in the question) then you could remove obj:
function test(val) {
console.log(val + ": " + window[val]);
}
var val1 = 1;
var val2 = 2;
test("val1");
test("val2");
It seems what you want to do something like this:
var argumentName = /([^\s,]+)/g;
// fu is a function
// fu.toString look like: function myFunction (param[, param]*) { code }
function getParamNames(fu) {
var f = fu.toString();
return f.slice(f.indexOf('(')+1,f.indexOf(')')).match(argumentName);
}
Then you might want to create an helper which will take every functions:
// I choosed the console as an output, but you can set anything
function displayParameters(fu) {
var _params = getParamNames(fu);
if(_params!==null) {
for(var i=0;i<_params.length; i++) {
console.log(_params[i]);
}
} else { console.log('no parameters'); }
}
And, you will need to call: displayParameters(test);
In a function you will be using a parameter. So in that case the "variable name" will always be the name of the parameter. In this case getting the string value will always be test. I would assume this is not what you want. You were correct that the best way to do this is to use an object and iterate over the key, values. You would do this like:
var test = {
"test" : "value"
};
function test (test) {
var k, $test = $('.test');
for(k in test){
$test.append(k + "<br>");
}
}
Also, I do not think there is a way to get the variable string name. So the above would be the way to get the name of a variable.
function checkData() {
var temp = 0;
var totalMarks = countMark(temp);
if (totalMarks != 100)
window.alert("Marks must total 100");
}
function countMark(mark) {
var totalMark = 0;
totalMark += parseInt(mark)
return totalMark;
}
function doAdd() {
var taskid = document.getElementById("taskid").value;
var taskname = document.getElementById("taskname").value;
var taskmark = document.getElementById("taskmark").value;
if (taskid.length === 0)
window.alert("Task Id cannot be empty!");
if (taskname.length === 0)
window.alert("Task name cannot be empty!");
if (taskmark.length === 0)
window.alert("Task Mark cannot be empty!");
else if (!markpattern.test(taskmark))
window.alert("Invalid data in mark field");
var marks = parseInt(document.getElementById("taskmark"));
if (marks < 0 || marks > 100)
window.alert("Marks out of range. Please re-enter");
countMark(marks);
}
My question is when i keep call the doAdd() function. my marks will keep adding . want to do like passing reference like in C++ . my function countMark(...) will keep adding .
after that, when my form submitted, my form will call the function checkData()
If my totalmark is not 100 . will prompt out the alert and error.
but my code is not working . I guess that my countMark function wrong somewhere
If I understand you correctly, you're looking for the equivalent of a static variable - something that gets initialized the first time the function is called, and keeps it's value for subsequent calls.
Take a look at this related question: https://stackoverflow.com/a/1535650/2444111
The top answer (by CMS) is talking about class-based static variables, which are not quite the same thing.
The second answer (by Pascal MARTIN) is what you're looking for. It takes advantage of the fact that JS functions are also objects, and stores the variable as a property of the function object. This is a better solution than using a global variable (or a property of window, which is what a global actually is)
There are several issues in your code and it's really hard to say what your intention was. But I will address what I found.
In the following piece of code you are requesting a DOM Element and try to parse it as an Integer. The result of that type convertion is always NaN. Maybe wanted to get the value attribute of your element, like you did before. (Also, don't request the same element multiple times. Request it once, save the result in a variable and use that variable from that on).
var marks = parseInt(document.getElementById("taskmark"));
if (marks < 0 || marks > 100)
window.alert("Marks out of range. Please re-enter");
countMark(marks);
Your function countMark is pretty useless, because it will always return whatever Number you pass to it (see comments in your code).
function countMark(mark) {
var totalMark = 0; //create a new variable with value 0
totalMark += parseInt(mark) //add "mark" to that variable
return totalMark; //return that variable => 0 + mark = mark (and if mark = NaN => 0 + mark = NaN)
}
Maybe you wanted to make totalMark a global variable, than you would need to define it outside of your function:
var totalMark = 0;
function countMark(mark) {
totalMark += parseInt(mark);
return totalMark;
}
Last but not least, lets analyse your function checkData:
function checkData() {
var temp = 0; //create a local variable with value 0
var totalMarks = countMark(temp); //pass 0 to countMark => return 0 => totalMarks = 0
if (totalMarks != 100) //always true since totalMarks is always 0
window.alert("Marks must total 100"); //will always alert
}