Combine two variables into one input attribute JS - javascript

I have a input field
<input required id={'odds' + index} type="text" step="any" className="form-control validate" value={this.state.odds + ' ' + index} onChange={this.onChange} />
Where I'm trying to combine the value attribute
value={this.state.odds + ' ' + index}
value={this.state.odds + index}
value={this.state.odds`${index}`}
value={this.state.odds `${index}`}
I tried all these, but it didn't work. How do you combine a state and a index in an array map?
Expected result: this.state.odds0 where index is 0 and it calls the state element
Example of what I'm getting:
this.state.odds is set to 1.5
this.state.odds0 is set to 5
If index is 0 I get ' 1.5 0 ' or ' 1.50 ' with the commands over. I want to get ' 5 '.

You are not getting the desired result because this.state.odds returns a number and you are trying to join it with another number by string concatenation but that will just give you a string. It won't get the value you want from the state
To get the required value from the state, try
value={this.state['odds' + index]}

You are using the wrong approach, you can't put JavaScript code on the value attribute directly on the HTML, instead you should change it from a script tag.
Let me give you an example:
We first create our input element on or HTML, note the id atrribute, it should be unique across all elements of your HTML document or it will not work properly.
<input id="changeThisToYourUniqueID">
Then we create another element, the script element, this is where we will manipulate our code.
<script></script>
We write the javascript code inside the script element, setting the value of the object to be the sum of the constant and the index.
<script>
let timesWeWantToLoop = 3
for(let index = 0; index < timesWeWantToLoop; index++){
document.getElementById("changeThisToYourUniqueID").value = "holamigos!"+index;
}
</script>
The change will happen very fast, so if you really need to see the change happening you can use a recursive function adding a delay to it with the native JavaScript setTimeout() function.
<input id="changeThisToYourUniqueID">
<script>
let index = 0;
let timesWeWantToLoop = 3
function myLoop() {
document.getElementById("changeThisToYourUniqueID").value = "holamigos!"+index;
setTimeout(function() {
index++;
if (index < timesWeWantToLoop) {
myLoop();
}
}, 1000)
}
myLoop()
</script>
Note: The example will not work under variable input situations, on those cases you need to create an event listener to see when the input value changes.
Cheers!

Related

How to loop through functions by name in P5js / JavaScript

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

how do i create a simple onclick add function()

i try to do these code and expecting it for increase by 1 everytime i click on the button but it returns me NaN instead.
im really new to javascript. really hope someone could help me!
thanks in advance.
function add(){
var sum = parseInt(1);
var adding = adding + sum;
document.getElementById("amt1").innerText = adding;
}
I see, here you've asked two problems:
Why adding is NaN
At line #2, you haven't initialized variable adding, hence in RHS adding is undefined.
Therefore, the RHS block adding + sum; is evaluated as undefined + 1, which evaluates to NaN
How to use onClick()
W3School's tutorial on onClick()
Here is your code in working state (HTML + JavaScript):
var adding = 0; // initialization. This is the step, that your code was missing
function add() {
var sum = parseInt(1);
adding = adding + sum;
document.getElementById("amt1").innerText = adding;
}
<h1>The onclick Event</h1>
<button onclick="add()">Click me</button>
<p id="amt1"></p>
You could take a closure over the sum and take the returned function for adding to the value.
var add = function(sum) {
return function () {
document.getElementById("amt1").innerHTML = ++sum;
};
}(0);
<span id="amt1">0</span> <button onclick="add()">add</button>
You're making the assignment in the local scope of the function, so every time the function executes, it's going to assign the value 1 to the 'sum' variable. Next, you're creating the variable 'adding' by trying to assign the value of adding, which doesn't exist yet.
It seems like the goal of your function is to just increment the value of 'amt1' by one.
function add(elId){
let currentAmt = document.getElementById(elId).innerText;
currentAmt = parseInt(currentAmt) + 1;
document.getElementById(elId).innerText = currentAmt;
}
By passing in the element ID, your function can now be applied to any element. It parses the integer from its current inner text, adds 1, then sets the new amount to the inner text of the element.
you might need to have a look on this post- Increment value each time when you run function
about how to increment, the idea is keep the variable outside the function as in you case,
you dont need parseInt as its used for parsing integers from a string.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
you need to keep the sum variable outside function. following is the general function to add
var n = 0;
function add(value){
n += value;
return n;
}
try it
document.getElementById("amt1").addEventListener("click", displayDate);
function displayDate() {
var node = document.getElementById('amt1');
document.getElementById("amt1").innerHTML = parseInt(node.textContent)+1;
}
<button id="amt1">1</button>
You're using an undefined variable adding to make your calculation that's why you get a NaN as a result :
var adding = adding + sum : the variable adding isn't yet initialized so it's value equals to undefined which give us var adding = undefined + sum = NaN. See next example :
var sum = parseInt(1);
console.log('typeof "adding" before initialization is ' + typeof adding + ' and it equals "' + adding + '"');
var adding = adding + sum;
console.log('typeof "adding" after initialization is ' + typeof adding + ' and it equals "' + adding + '"');
BTW, you don't need parseInt in order to put manually a number, sum = parseInt(1) is the same as sum = 1 but the later is faster.
And now here's how to accomplish your task :
/**
* btn: the button to be clicked to increment the counting.
* counterTxt: the "p#counter" element that prints the counting.
* counter: keeps track of the number of the clicks made.
**/
const btn = document.getElementById('btn'),
counterTxt = document.getElementById('counter');
let counter = 0; /** holds the number of clicks **/
/** click event handler for the "button" **/
btn.addEventListener('click', () => counterTxt.textContent = ++counter); /** update the "p#counter" text and increment the counter **/
<button id="btn">click to increment</button>
<p id="counter">0</p>

Javascript: for loop not working as expected

Im currently trying to set up a loop that returns exif data from an image using piexifjs.
Up to this point the code provided by the developer of piexif is working correct in my Vue.js environment.
The loop which is used to display the exif-data inside the console looks like this:
for (let ifd in exifObj) {
if (ifd == "thumbnail") {
continue;
}
console.log("-" + ifd);
for (let tag in exifObj[ifd]) {
console.log(" " + piexif.TAGS[ifd][tag]["name"] + ":" + exifObj[ifd][tag]);
}
}
Works fine, but if I try to edit it to return HTML and display the exif information on my Site it just returns one line of information. Here's the code:
for (let ifd in exifObj) {
if (ifd === "thumbnail") {
continue;
}
const exifInfo = $(".modal-exif"),
exifInfoDetail = $(".modal-exif-detail");
exifInfo.html("ยป " + ifd);
for (let tag in exifObj[ifd]) {
exifInfoDetail.html("<li>" + piexif.TAGS[ifd][tag]["name"] + ":" + exifObj[ifd][tag] + "</li>");
}
}
I guess my loop is overwriting itself where it returns just one value, which, I guess, is fine inside the console since but not inside HTML?
Anyone got any Idea hwo to change the loop to return one line for each entry?
Thank you :)
In the console.log case, each iteration is writing to the console, whereas in the $(selector).html() case, you are overwriting the html content per iteration. The jquery html function states:
Set the HTML contents of each element in the set of matched elements.
That means that each iteration, the html content of $(".modal-exif-detail") is set to one single "<li>" + piexif.TAGS[ifd][tag]["name"] + ":" + exifObj[ifd][tag] + "</li>".
You need to use something like append if you want to continually add to a node, or build up the html string and only execute one html after the loop

innerHTML not working inside event handler function (Javascript)

I have created a function, updatePrice, which I have tied to the "click" event on the checkbox and radio buttons in my HTML form. Each checkbox and radio basically represents an item, with it's price as the value property of these <input> elements. When I check or uncheck any box, the function fires, loops through all elements in the form, and updates the total price of all the checked items into a div element I have below my form, with the id tag "priceOutput".
The following code works perfectly, printing out: The price of this item is $(price of item).
function updatePrice() {
var price = 0
for (i=0;i<=form.length;i++) {
var element = form[i]
if(element.checked) {
price+=parseInt(element.value)
}
document.getElementById("priceOutput").innerHTML = "The price of this item is $" + price + "."
}
}
But, if I switch the the last line around, the line is not printed at all:
function updatePrice() {
var price = 0
for (i=0;i<=form.length;i++) {
var element = form[i]
if(element.checked) {
price+=parseInt(element.value)
}
}
document.getElementById("priceOutput").innerHTML = "The price of this item is $" + price + "."
}
Why must I write the line in the {} of the for in order to work. Doesn't the price variable's scope extend over the entire updatePrice function?
I'm still rather new to programming, so do forgive me if this is an elementary question.
It seems to me that it isn't printing because you are causing an error. Since array indexing starts at 0 your for loop should not use <= but rather < :
for (i=0;i<form.length;i++) {
...
}
The reason why nothing gets printed then is because on the last loop the function errors and you setting the inner HTML never gets executed.
Seems like there is an error with your code, how about adding var to your for loop and removing the = from i<=form.length
for (var i = 0; i < form.length; i++)

JS. How to get list of div's with similar class name?

I have html, like this:
<div id="c0" class="bz_comment bz_first_comment"></div>
<div id="c1" class="bz_comment"></div>
<div id="c2" class="bz_comment"></div>
<div class="bz_add_comment"></div>
How can I get array of all the div's (3 div in example) by class that's starts with "bz_comment[anysymbols]" in JavaScript (not using JQuery)?
Or can i get array of div's by id that's starts with "c[numeric_value]"?
[numeric_value_can_consist_of_some_numbers]
It's the similar question like stackoverflow.com/questions/1225611/ (but i don't have reputation to ask in that question). Thanks in advance.
You should use .querySelectorAll
var matching = document.querySelectorAll('[class*="bz_comment"]')
I see some worrying things in your code though:
You have sequential numeric IDs, consider using an Array to represent sequential data instead.
You are selecting things by class name identifiers, if you must do this - use a data-* attribute instead. Better yet, store the elements in an array instead and have a direct reference to them.
You can write a function to process elements on the page that contain the class you're looking for:
function containsClass(matchClassName) {
var matches = new Array();
var elems = document.getElementsByTagName('div'), i;
for (i in elems) {
if((' ' + elems[i].className + ' ').indexOf(' ' + matchClassName + ' ') > -1) {
matches.push(elems[i]);
}
}
return matches;
}
now you can write
var matches = containsClass('bz_comment');

Categories

Resources