Possible to create new variable with new name upon button onclick? - javascript

I was wondering if it was possible to create a new variable when a button is pressed. For example: if I have a variable named enemy1 and the button is pressed, Can a variable named enemy2 be created? I'm sorry if this seems like a silly question. I wanted to create a for loop where I can define a variable thats name changes depending on 'i'.

Probably best to use an Array (adding new values on click) or Object (adding new keys on click). I think you should use an Array, so here is an example:
const enemies = [];
class Enemy {
speak () {
return 'COME AT ME BRO!!!';
}
}
document.querySelector('#createEnemy').addEventListener('click', function(event) {
const enemy = new Enemy();
enemies.push(enemy);
console.log(enemies.length, 'enemies say', enemy.speak());
}, false);
<button id="createEnemy">Create Enemy</button>

You do not require dynamic variable, instead you need one variable that would contain dynamic size (dynamic number of enemies). Following is the code you need. Here you can see demo
<button id='createEnemy' onclick='addEnenemy()'>Add Enenmy</button>
<div id='enemiesContainer'> </div>
<script>
var enemies = [];
var enemyDiv = document.getElementById('enemiesContainer');
function addEnenemy() {
var newEnenmy = 'enemy'+(enemies.length+1);
enemies.push(newEnenmy);
//following will show it in your page
enemyDiv.innerHTML = enemyDiv.innerHTML + '<br/><label>'+newEnenmy+'</label>';
console.log(enemies); //shows in console
}
</script>

Related

Object Modify Problem on Dynamically Created Element EventListener

I ran into a very interesting problem during use event listeners on dynamically created elements using Vanilla Javascript. I will first define the problem and later post the code.
I create dynamic html elements using javascript and during creation process I add "click" event listeners on each newly created object. And inside this event event listener I change a different property of a GLOBAL object. I mean, when you click a dynamically created element, each element modifies a different property of this global object.
Problem occurs here, I dynamically select the different property of the global object. So for each element it modifies a different property of th global object. BUT when I run the code, I see that each element only changes the latest property of the global object. Meaning that each element changes the same property of that object and it is the latest property of the object. Here the code:
var filter = {1:false, 4:false, 7:false, 11:false, 8:false} //global object
var productsAndIndexes = {a:1, b:4, c:7, d:11, e:8 } //another global object used for looping
function createEmptyFilter(){
var hdr = document.querySelector("div.content .headers");
for(var product in productsAndIndexes){
var inp = document.createElement("input");
inp.setAttribute("type", "checkbox");
var filterInd = productsAndIndexes[product];
inp.addEventListener("click" , (e) => {
if(e.target.checked){
filters[ filterInd ] = true;
}else{
filters[ filterInd ] = false;
}
});
hdr.appendChild(inp);
}
}
createEmptyFilter();
Every time I check a checkbox, I got filter = {1:false, 4:false, 7:false, 11:false, 8:true}. But instead each checkbox should modify its related part in the object.
Any explanation and solution about the problem is appreciated (although I am not 15 rep :) )
Thanks
The issue is that your filterInd variable is declared with var meaning it is function scoped, not scoped to your for loop block. That means that each loop iteration will overwrite the same variable, so the click handlers all close over that same variable, not unique variables with different values. Declare it with const or let instead, and the click handler will reference the value unique to the loop iteration.
Since you're using a browser modern enough to support =>, then you probably support let and const; there's really no good reason to ever use var nowadays.
const filter = {1:false, 4:false, 7:false, 11:false, 8:false} //global object
const productsAndIndexes = {a:1, b:4, c:7, d:11, e:8 } //another global object used for looping
function createEmptyFilter(){
const hdr = document.querySelector("div.content .headers");
for (let product in productsAndIndexes) {
const inp = document.createElement("input");
inp.setAttribute("type", "checkbox");
const filterInd = productsAndIndexes[product];
inp.addEventListener("click", e => {
if (e.target.checked) {
filters[filterInd] = true;
} else {
filters[filterInd] = false;
}
});
hdr.appendChild(inp);
}
}
createEmptyFilter();

Create javascript variable with button click no jQuery

I am wondering how I would create a variable on the click of a button, so I could make a random name generator, like this:
<input class="varValue" placeholder="Name to be generated">
<button class="createVar></button>
<script>
var createVar = document.querySelector(".createVar");
var varValue = document.querySelector(".varValue");
var nameNumber = 0;
var getValue = function(){
varValue.value = //new var with ascending values or something;
nameNumber = nameNumber + 1;
};
createValue.addEventListener("click", getValue(), false");
//then some Math.random using, nameNumber, anyway I'll figure it out
</script>
So how would I make the variables on the click of the button?
Also no jQuery please.
The function getValue() [which I don't see declared, so it should be declared somewhere] is in charge of any new logic attached to that event in this case.
To create and do something with those variables simply do it right inside that function.
I believe you meant createVar.addEventListener() and not createValue

How to work with variables dynamically in javascript?

I need to work with variables dynamically, and get them dynamically too. The first thing I need to know is:
How to save a variable reference(NOT its value) in a collection?
Example:
var divA = "<div>my div A</div>";
var divB = "<div>my div B</div>";
var divC = "<div>my div C</div>";
Then, save in a collection:
var mySet = new Set();
function returnDivA(){
return divA;
}
function returnDivB(){
return divB;
}
function returnDivC(){
return divC;
}
mySet.add(returnDivA());//I would like save the varible ref in a collection.
mySet.add(returnDivB());
mySet.add(returnDivC());
I want the Set collection to save the variables(NOT its values), it means:
var mySet = new Set(divA, divB, divC);
Then, with that, my intent is to do something like that:
var totalOfDivs;
for(var i = 0; i < mySet.size; i++){
totalOfDivs += mySet[i];
}
$("#anotherDIV_to_show_all_divs").html(totalOfDivs);//Then, here, I want to show all divs in the screen.
I would like suggestions, please!
It solved my problem to put variable dynamically in html using this in a for loop:
$("#anotherDIV_to_show_all_divs").append(mySet[i]);
About saving javascript variable reference in a Collection, I understand that I can't do that, because of the answer of the adeneo in comment:
"There is no "reference", all variables are pass-by-value in javascript..."
Read the documentation about set.
enter link description here
I guess you have to loop your set like this.
var totalOfDivs= "";
for (let item of mySet.values()) {
totalOfDivs+= item;
//console.log(item);
}
$("#anotherDIV_to_show_all_divs").html(totalOfDivs);

JavaScript - Creating Label with same properties multiple times

I am using JavaScript to create a Label object. This Label object should be created when an event occurs. All is working fine. But, when the same event is triggered again, this is where I am seeing a problem: "adding element with duplicate id". I have tried to destroy/delete the Label object and create it every time the event is triggered. But No Luck. Any Suggestions??
Please suggest, how to re-create the Label object with same properties again and again?
Please find the code
switch(locDetail)
{
case 'K1':
klocation = "INDIA";
//var oLocLabel1 = null;
//alert("INDIA");
//document.getElementById('LocLabelContent').innerHTML = "";
var oLocLabel1 = new sap.ui.commons.Label("LocationDetailsLabel1");
oLocLabel1.setText(klocation);
oLocLabel1.placeAt("LocLabelContent1");
//delete oLocLabel1;
//document.getElementById('LocLabelContent').innerHTML = klocation;
oLocLabel1.destroy();
break;
If we create a object with new properties (appending a counter). Will that not cause extra objects?
I'm guessing you're creating a label element, if so you can create the label with all the properties and just clone it every time you need a new one, and set the ID with an increasing counter to get unique ID's, something like :
var label = document.createElement('label'),
counter = 0;
label.innerHTML = 'some label text';
label.style.color = 'red';
someElement.addEventListener('click', function() {
var lbl = label.cloneNode(true);
lbl.id = 'label_' + (++counter);
document.body.appendChild(lbl);
}, false);

Alternative to using eval()

I've heard a lot of rumblings about how "evil" or even "misunderstood" the eval function is, so I've decided to remove it from my code. The problem is I don't know what to replace it with.
Here's a quick rundown of my current code. I have a series of arrays (just 2 for the example below) declared at the beginning, and then based on a button click one of them gets loaded into a variable that is passed into a function.
Here's some basic HTML
<div class="button" data-name="button1">Button1</div>
<div class="button" data-name="button2">Button2</div>
and the JS (with jQuery)
var butName = null;
var eArray = null;
var button1Logo = ["..path/to/pic1.png","..path/to/pic2.png"];
var button2Logo = ["..path/to/pic3.png","..path/to/pic4.png"];
$(".button").mouseup(function(){
/*give a butName*/
butName = $(this).attr("data-name");
/*give the array from the button*/
eArray = eval(butName + "Logo");
});
Doing it this way assigns the array to the variable and not just a string that says "butnameLogo" which is why I used eval. But I'm looking to get away from that.
I know I can add a new attribute to the html and just retrieve that for the variable but I don't want to add more html when I can possibly do it with JS.
I've also tried making an object with strings loaded into it as seen in this answer: https://stackoverflow.com/a/16038097/1621380 but that resulted in just a string again, and not assigning a variable.
Wondering if you smart people have any better suggestions!
Replace
var button1Logo = ["..path/to/pic1.png","..path/to/pic2.png"];
var button2Logo = ["..path/to/pic3.png","..path/to/pic4.png"];
with an object, where the keys are your button names:
var buttonLogos = {
button1: ["..path/to/pic1.png","..path/to/pic2.png"],
button2: ["..path/to/pic3.png","..path/to/pic4.png"]
};
Then instead of the eval you can simply do
eArray = buttonLogos[butName]
(or buttonLogos[butName + "Logo"] if you want to call the keys button1Logo and button2Logo, but I can't really see the point now that they are nicely contained within a buttonLogos object)
Use an object:
var butName = null;
var buttonsLogos = {
button1: ["..path/to/pic1.png", "..path/to/pic2.png"],
button2: ["..path/to/pic3.png", "..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/*give a butName*/
butName = $(this).attr("data-name");
/*give the array from the button*/
eArray = buttonsLogos[butName];
});
Consider making the data available as properties of an object, then you can control access to the object through scope and only need one (global?) variable for all such data.
If global scope is needed, then:
var dataObj = {
button1Logo: ["..path/to/pic1.png","..path/to/pic2.png"],
button2Logo: ["..path/to/pic3.png","..path/to/pic4.png"]
}
and later:
var eArray = dataObj[this.data-name + 'Logo'];
You may want to call the data object something more meaningful than dataObj though.
The best option is to define an object which holds all our button paths:
var buttons = {
"1": ["..path/to/pic1.png", "..path/to/pic2.png"],
"2": ["..path/to/pic3.png", "..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/* give a butName */
var butName = $(this).attr("data-name");
/* give the array from the button */
var eArray = buttons[butName];
});
If your variables reside in the global scope, you could use the bracket notation to access them:
eArray = window[butName + "Logo"];
Note that this solution is not recommended. The first code sample is much cleaner and more maintainable.
Imagine a situation where you would have to move all the code into a 'deeper' context (!= global context). Nothing would work anymore.
You can do this very nicely with arrays and array indexes. You needn't find and use variable names at all. Even your data- attributes are unnecessary.
var eArray;
var buttonLogos = [
["..path/to/pic1.png","..path/to/pic2.png"],
["..path/to/pic3.png","..path/to/pic4.png"]
];
var buttons = $(".button").mouseup(function(){
var idx = buttons.index(this);
eArray = buttonLogos[idx];
});
The key line in this is buttons.index(this). This method call gets the position of the current element among all the elements matched by $(".button"). We then use this index to select the relevant element from the buttonLogos array.
You're taking a very circuitous route by using eval here.
You'd be much better off doing something like this:
var paths = {
button1: ["..path/to/pic1.png","..path/to/pic2.png"],
button2: ["..path/to/pic3.png","..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/*give the array from the button*/
eArray = paths[$(this).attr("data-name")];
});
eval should only be used if you need to execute code (usually from a 3rd party source), and even that is rare. If you ever find yourself saying "i should use eval here", there's almost definitely a better alternative, and you should try and find it.

Categories